只需循环遍历
a1
,并查看在您创建的字典中是否存在匹配的键即可:
mapping = dict(zip(a, b))
matches = [mapping[value] for value in a1 if value in mapping]
示例:
>>> 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]
然而,请注意你正在使用 浮点数。由于浮点数是十进制值的二进制近似值,因此可能无法完全匹配值;例如,值2.999999999999999
(15个9)可能被Python的str()
函数呈现为3.0
,但并不等于3.0
:
>>> 2.999999999999999
2.999999999999999
>>> str(2.999999999999999)
'3.0'
>>> 2.999999999999999 == 3.0
False
>>> 2.999999999999999 in mapping
False
如果您的输入列表
a
已排序,您可以使用
math.isclose()
函数(或其后移版本),结合
bisect
模块 来保持匹配的高效性:
import bisect
try:
from math import isclose
except ImportError:
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
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])
这个测试每个输入值最多从a
中提取两个值;一个保证等于或低于(在index - 1
),另一个更高的值。对于你的样本a
,值2.999999999999999
被二分到索引3
,位于2.1
和3.0
之间。由于isclose(3.0, 2.999999999999999)
为真,这仍然可以让您将该值映射到b
中的4
。