【问题标题】:How to iterate through a list of tuples containing three pair values?如何遍历包含三对值的元组列表?
【发布时间】:2017-03-04 00:45:34
【问题描述】:

我想从列表中删除第一个元素相同的元组,因为我将字母对视为具有相同的值,尽管它们的排序。这是我试图遍历的列表,名为tuples2

[(3, 'A', 'C'), (3, 'C', 'A'), (2, 'B', 'C'), (2, 'C', 'B'), (1, 'A', 'B'), (1, 'B', 'A')]

我当前的代码:

for i in list(tuples2):
    if i[0] == i+1[0]:
        tuples2.remove(i)
    print tuples2

...正在抛出此错误:

line 6: if i[0] == (i+1)[0]: TypeError: can only concatenate tuple (not "int") to tuple

如果我想结束,我应该如何修改我的代码来解决这个问题 [(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')]?

【问题讨论】:

    标签: python list tuples


    【解决方案1】:

    此代码中有很多危险信号。您不应该修改您正在迭代的列表,这将导致您停止跳过项目。 编辑我现在看到您在 for 循环中复制了列表,但是,以下方法仍然更安全一些。您可以向后迭代,但构建 new 列表可能更容易。一种直接的方法是跟踪已经见过的第一个元素,并且只有在您之前没有见过第一个元素时才添加:

    In [1]: data = [(3, 'A', 'C'), (3, 'C', 'A'), (2, 'B', 'C'), (2, 'C', 'B'), (1, 'A', 'B'), (1, 'B', 'A')]
       ...:
    In [2]: seen = set()
    
    In [3]: new_data = []
       ...: for triple in data:
       ...:     first = triple[0]
       ...:     if first in seen:
       ...:         continue
       ...:     seen.add(first)
       ...:     new_data.append(triple)
       ...:
    
    In [4]: new_data
    Out[4]: [(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')]
    

    使用.remove 效率非常低。它将您的算法更改为 O(n^2) 而不是 O(n)。

    【讨论】:

    • 非常感谢,这非常简单,而且效果很好。我真的很感谢你的帮助!以这种方式跟踪已经看到的元素正是我需要做的
    【解决方案2】:

    您可以读入由第一个组件键入的字典,然后读出值:

    tuples = [(3, 'A', 'C'), (3, 'C', 'A'), (2, 'B', 'C'), (2, 'C', 'B'), (1, 'A', 'B'), (1, 'B', 'A')]
    d = {x:(x,y,z) for x,y,z in tuples}
    tuples = list(d.values())
    

    结果tuples:

    [(1, 'B', 'A'), (2, 'C', 'B'), (3, 'C', 'A')]
    

    【讨论】:

    • 非常感谢,这也很有效,但是保留列表的排序顺序是我希望得到的答案,而 juanpa.arrivillaga 显示了这一点。
    【解决方案3】:

    你对i in list(tuples2) 的迭代有一个错误的概念:使用这种语法,i 不是索引,而是元组本身。所以,你不能这样做i+1[0]

    首先,我建议你这样做:

    tuples_list = list(tuples2)
    

    要解决这个问题,您可以使用 python 建议的xrange(或range),它将按索引工作:

    for i in xrange(len(tuples_list)-1):
        if tuples_list[i][0] == tuples_list[i+1][0]:
            #Do what you want
    

    【讨论】:

    • 谢谢,但是当我按照您的建议进行操作时,它会抛出“如果 tuples_list[i] == tuples_list[i+1]: IndexError: list index out of range”
    • @CoraColeman 抱歉,正在修复它 - 当然是最后一次迭代导致它。
    【解决方案4】:

    只需按第一个元素分组并取每个组中的第一个。

    >>> [next(g) for _, g in itertools.groupby(tuples2, lambda x: x[0])]
    [(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')]
    

    甚至更简单:

    >>> tuples2[::2]
    [(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')]
    

    【讨论】:

    • 我认为实际上在这种特殊情况下tuples[::2] 是正确的方法。
    【解决方案5】:

    您可以像这样使用来自itertools 模块的groupby 解决您的问题:

    from itertools import groubpy
    
    a = [(3, 'A', 'C'), (3, 'C', 'A'), (2, 'B', 'C'), (2, 'C', 'B'), (1, 'A', 'B'), (1, 'B', 'A')]
    final = [list(v)[0] for _,v in groupby(sorted(a), lambda x: x[0])]
    
    print(final)
    

    输出:

    >>> [(1, 'A', 'B'), (2, 'B', 'C'), (3, 'A', 'C')]
    

    否则,如果您需要final 列表的顺序与您在问题中给出的顺序相同,则可以将其反转:

    final = list(reversed(final))
    # OR
    #final = sorted(final, reverse = True)
    print(final)
    

    输出:

    >>> [(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')]
    

    【讨论】:

    • 在这里使用sorted 只是碰巧有效,不能推广。
    • 我也可以使用list(reversed(final))
    • 我不这么认为。我认为reversed 再次碰巧 工作。当你一开始排序时,你失去了排序,所以如果原始列表没有按某种排序顺序,你将无法取回它。
    【解决方案6】:

    直接问题

    这是什么意思?

    i+1[0]
    

    i 是一个元组;您正在尝试使用 i 作为索引和元素。您需要的迭代更像是:

    for i in range (len(tuples2)):
        if tuples2[i] == tuples2[i+1]:
    

    ... 仍然无法完成这项工作。这将检查整个元组的相等性。但是,您说您关心的只是第一个元素的相等性。然后你会想要:

        if tuples2[i][0] == tuples2[i+1][0]:
    

    这是根据您当前的代码;其他人已经向您展示了更多“Pythonic”的方法。

    一般解决方案

    此代码假定元组的其他元素相等,具有相同第一个元素的元组在列表中相邻,并且匹配的元组仅成对出现。您的列表是否可能包含以下内容:

    tuples2 = [(3, 'A', 'C'), (3, 'C', 'A'), 
               (2, 'B', 'C'), (2, 'C', 'B'), 
               (1, 'A', 'B'), (1, 'A', 'Z'), (1, 'B', 'A')]
    

    附加的“Z”元素可能被埋在“3”元素之间?无论如何,即使您对列表进行排序,您也会在其他“1”元素之间获得“AZ”元素。

    如果这对您来说是个问题,那么我建议您首先将每个元组转换为一个列表,将元素排序。例如,thi'b 会将 (1, 'B', 'A') 转换为 [1, 'A', 'B']。然后使用任何给定的方法来消除重复,包括您已经编程的方法。我通常通过将事物转回元组然后形成一个集合来做到这一点——这会自动消除重复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-18
      • 2013-05-26
      • 2019-11-16
      • 2016-08-21
      • 2018-06-11
      • 2021-09-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多