我有一个清单
a = [1.0, 2.0, 2.1, 3.0, 3.1, 4.2, 5.1, 7.2, 9.2]
我想将此列表与其他列表进行比较,但我想以数字顺序提取有关列表内容的信息。所有其他列表的元素与a
相同。
所以我试过这个
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]
我想将a1与a进行比较并提取字典值[3, 5, 6, 8]
。
答案 0 :(得分:6)
只需遍历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()
function(或其后端)以及bisect
module来保持匹配效率:
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])
每个输入值最多可测试两个a
个值;一个保证等于或低于(index - 1
)和下一个更高的值。对于您的示例a
,值2.999999999999999
被分成两半,以3
和2.1
之间的3.0
为索引。由于isclose(3.0, 2.999999999999999)
为真,您仍然可以将该值映射到4
中的b
。