I have one list
a = [1.0, 2.0, 2.1, 3.0, 3.1, 4.2, 5.1, 7.2, 9.2]
I want to compare this list with other list but also I want to extract the information regarding the list content in numeric order.All other list have the elements that are same as a
.
So I have tried this
a = [1.0, 2.0, 2.1, 3.0, 3.1, 4.2, 5.1, 7.2, 9.2]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print dict(zip(a,b))
a1=[2.1, 3.1, 4.2, 7.2]
I want to compare a1 with a and extract dict values [3, 5, 6, 8]
.
1 Answer 1
Just loop through a1
and see if there is a matching key in the dictionary you created:
mapping = dict(zip(a, b))
matches = [mapping[value] for value in a1 if value in mapping]
Demo:
>>> a = [1.0, 2.0, 2.1, 3.0, 3.1, 4.2, 5.1, 7.2, 9.2]
>>> b = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a1 = [2.1, 3.1, 4.2, 7.2]
>>> mapping = dict(zip(a, b))
>>> [mapping[value] for value in a1 if value in mapping]
[3, 5, 6, 8]
However, take into account that you are using floating point numbers. You may not be able to match values exactly, since floating point numbers are binary approximations to decimal values; the value 2.999999999999999
(15 nines) for example, may be presented by the Python str()
function as 3.0
, but is not equal to 3.0
:
>>> 2.999999999999999
2.999999999999999
>>> str(2.999999999999999)
'3.0'
>>> 2.999999999999999 =わ=わ 3.0
False
>>> 2.999999999999999 in mapping
False
If your input lists a
is sorted, you could use the math.isclose()
function (or a backport of it), together with the bisect
module to keep matching efficient:
import bisect
try:
from math import isclose
except ImportError:
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
# simplified backport, doesn't handle NaN or infinity.
if a == b: return True
return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
result = []
for value in a1:
index = bisect.bisect(a, value)
if index and isclose(a[index - 1], value):
result.append(b[index - 1])
elif index < len(a) and isclose(a[index], value):
result.append(b[index])
This tests up to two values from a
per input value; one that is guaranteed to equal or lower (at index - 1
) and the next, higher value. For your sample a
, the value 2.999999999999999
is bisected to index 3
, between 2.1
and 3.0
. Since isclose(3.0, 2.999999999999999)
is true, that would still let you map that value to 4
in b
.