如何遍历包含三对值的元组列表?

时间:2017-03-04 00:45:35

标签: python list tuples

我想从第一个元素相同的列表中删除元组,因为我将字母对视为具有相同的值,尽管它们有序。这是我试图迭代的列表,名为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')]

6 个答案:

答案 0 :(得分:4)

此代码中有很多红旗。您不应该修改正在迭代的列表,这将导致您停止跳过项目。 编辑我现在看到您在for-loop中复制了列表,但是,以下方法更安全一点。您可以向后迭代,但构建列表可能更容易。一种简单的方法是跟踪已经看到的第一个元素,并且只有在您之前看不到第一个元素时才添加:

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)。

答案 1 :(得分:3)

你对i in list(tuples2)的迭代有一个错误的概念:使用这种语法,我不是索引,而是实际上是元组本身。因此,您无法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

答案 2 :(得分:3)

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

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')]

答案 3 :(得分:2)

您可以使用groupby模块中的itertools解决您的问题:

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')]

答案 4 :(得分:2)

只需按第一个元素分组,然后取每组的第一个元素。

>>> [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')]

答案 5 :(得分:1)

立即问题

这是什么意思?

i+1[0]

是一个元组;您正尝试将 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"元素?无论如何,即使您对列表进行排序,您也可以获得" AZ"另一个" 1"之间的元素元件。

如果这对您来说是个问题,那么我建议您先将每个元组转换为一个列表,然后将元素按顺序排序。例如,您可以将(1,' B' A' A')转换为[1,' A',' B&#39 ]。然后使用任何给定的方法来消除重复,包括您已编程的重复。我通常通过将事物重新转换为元组然后形成一组来自动消除重复。