Python中列表元素的成对比较

4

给定以下列表:

snplist = [[1786, 0.0126525], [2463, 0.0126525], [2907, 0.0126525], [3068, 0.0126525], [3086, 0.0126525], [3398, 0.0126525], [5468,0.012654], [5531,0.0127005], [5564,0.0127005], [5580,0.0127005]]

我希望对列表中每个子列表的第二个元素进行成对比较,即比较[1786, 0.0126525] 中的0.0126525 是否等于[2463, 0.0126525] 中的0.0126525。如果是,则按照代码所示打印输出。

使用for循环可实现该结果:

for index, item in enumerate(snplist, 0):
    if index < len(snplist)-1:
        if snplist[index][1] == snplist[index+1][1]:
            print snplist[index][0], snplist[index+1][0], snplist[index][1]

在使用列表索引进行循环元素的成对比较时,我总是因为最后一个元素而遇到“索引超出范围”的错误。我通过添加条件来解决这个问题。
if index < len(snplist)-1:

我认为这不是最佳方法。我想知道在Python中进行列表元素的成对比较是否有更详细的方法?

编辑:我没有考虑到比较浮点数时的容差水平。如果两个浮点数相差0.001,我会认为它们相等。


2
你正在比较浮点数。定义“相等”的标准是什么?公差是多少? - timgeb
2个回答

10
你可以使用zipsnplist与除第一个元素外相同的列表一起压缩,然后进行比较,就像这样。
for l1, l2 in zip(snplist, snplist[1:]):
    if l1[1] == l2[1]:
      print l1[0], l2[0], l1[1]

由于你正在比较浮点数,我建议使用Python 3.5中的math.isclose函数,像这样:

def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
    return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

如果你想要0.001的公差,可以像这样进行比较

if is_close(l1[1], l2[1], 0.001):

嗯,OP正在使用Python2.7,你怎么导入'math.is_close'? - timgeb
@timgeb 这只是两行简单的代码。我希望他可以复制粘贴并使用它 :-) - thefourtheye

4

我建议您使用izip来创建一个项目-邻居对的生成器。不考虑比较浮点数的问题,代码应该如下所示:

>>> from itertools import izip
>>> lst = [[1,2], [3,4], [5,4], [7,8], [9,10], [11, 10]]
>>> for item, next in izip(lst, lst[1:]):
...     if item[1] == next[1]:
...         print item[0], next[0], item[1]
... 
3 5 4
9 11 10

比较浮点数时,请记得指定公差,不要使用 == 进行比较!

你可以为此定义一个 almost_equal 函数,例如:

def almost_equal(x, y, tolerance):
    return abs(x-y) < tolerance

在上面的代码中,使用almost_equal(item[1], next[1], tolerance)替代与==的比较。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接