如何在Python中比较列表?

时间:2016-03-07 13:12:28

标签: python

我有一个清单

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]

1 个答案:

答案 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被分成两半,以32.1之间的3.0为索引。由于isclose(3.0, 2.999999999999999)为真,您仍然可以将该值映射到4中的b