从元组列表中删除值

时间:2014-11-25 19:06:13

标签: python list python-2.7 tuples unique

我有一个元组列表,我只想返回第二列数据,只有唯一值

mytuple = [('Andrew','Andrew@gmail.com','20'),('Jim',"Jim@gmail.com",'12'),("Sarah","Sarah@gmail.com",'43'),("Jim","Jim@gmail.com",'15'),("Andrew","Andrew@gmail.com",'56')]

期望的输出:

['Andrew@gmail.com','Jim@gmail.com','Sarah@gmail.com']

我的想法是遍历列表并将第二列中的项追加到新列表中,然后使用以下代码。在我沿着这条路走得太远之前,我知道有更好的方法可以做到这一点。

from collections import Counter
cnt = Counter(mytuple_new)
unique_mytuple_new = [k for k, v in cnt.iteritems() if v > 1]

6 个答案:

答案 0 :(得分:3)

您可以使用zip功能:

>>> set(zip(*mytuple)[1])
set(['Sarah@gmail.com', 'Jim@gmail.com', 'Andrew@gmail.com'])

或者作为性能较低的方式,您可以使用mapoperator.itemgetter并使用set来获取唯一元组:

>>> from operator import itemgetter
>>> tuple(set(map(lambda x:itemgetter(1)(x),mytuple)))
('Sarah@gmail.com', 'Jim@gmail.com', 'Andrew@gmail.com')

对某些答案进行基准测试:

我的回答:

s = """\
mytuple = [('Andrew','Andrew@gmail.com','20'),('Jim',"Jim@gmail.com",'12'),("Sarah","Sarah@gmail.com",'43'),("Jim","Jim@gmail.com",'15'),("Andrew","Andrew@gmail.com",'56')]
set(zip(*mytuple)[1])
"""
print timeit.timeit(stmt=s, number=100000)
0.0740020275116

icodez回答:

s = """\
mytuple = [('Andrew','Andrew@gmail.com','20'),('Jim',"Jim@gmail.com",'12'),("Sarah","Sarah@gmail.com",'43'),("Jim","Jim@gmail.com",'15'),("Andrew","Andrew@gmail.com",'56')]
seen = set()
[x[1] for x in mytuple if x[1] not in seen and not seen.add(x[1])]
"""
print timeit.timeit(stmt=s, number=100000)
0.0938332080841

哈桑回答:

s = """\
mytuple = [('Andrew','Andrew@gmail.com','20'),('Jim',"Jim@gmail.com",'12'),("Sarah","Sarah@gmail.com",'43'),("Jim","Jim@gmail.com",'15'),("Andrew","Andrew@gmail.com",'56')]
set([k[1] for k in mytuple])
"""
print timeit.timeit(stmt=s, number=100000)
0.0699651241302

Adem的回答:

s = """
from itertools import izip
mytuple = [('Andrew','Andrew@gmail.com','20'),('Jim',"Jim@gmail.com",'12'),("Sarah","Sarah@gmail.com",'43'),("Jim","Jim@gmail.com",'15'),("Andrew","Andrew@gmail.com",'56')]
set(map(lambda x: x[1], mytuple))
"""
print timeit.timeit(stmt=s, number=100000)
0.237300872803 !!!

答案 1 :(得分:1)

尝试:

>>> unique_mytuple_new = set([k[1] for k in mytuple])
>>> unique_mytuple_new
set(['Sarah@gmail.com', 'Jim@gmail.com', 'Andrew@gmail.com'])

答案 2 :(得分:1)

unique_emails = set(item[1] for item in mytuple)

列表推导将帮助您生成仅包含第二列数据的列表,并将该列表转换为set()可删除重复的值。

答案 3 :(得分:1)

您可以使用列表推导和集合来跟踪看到的值:

>>> mytuple = [('Andrew','Andrew@gmail.com','20'),('Jim',"Jim@gmail.com",'12'),("Sarah","Sarah@gmail.com",'43'),("Jim","Jim@gmail.com",'15'),("Andrew","Andrew@gmail.com",'56')]
>>> seen = set()
>>> [x[1] for x in mytuple if x[1] not in seen and not seen.add(x[1])]
['Andrew@gmail.com', 'Jim@gmail.com', 'Sarah@gmail.com']
>>>

此解决方案最重要的部分是保存订单,就像您的示例一样。只做set(x[1] for x in mytuple)或类似的东西会获得独特的项目,但他们的订单将丢失。

此外,if x[1] not in seen and not seen.add(x[1])看起来有点奇怪,但它实际上是一个巧妙的技巧,允许你在列表理解中添加项目(否则,我们需要使用for循环)

由于and在Python中执行短路评估,not seen.add(x[1])仅在x[1] not in seen返回True时才会被评估。因此,条件是x[1]是否在集合中,如果没有则添加它。

not运算符放在seen.add(x[1])之前,以便条件评估为True,如果x[1]需要添加到集合中(set.add返回{ {1}},被视为NoneFalsenot False)。

答案 4 :(得分:0)

明显简单的循环怎么样?无需创建列表然后转换为设置,只是不添加重复项。

mytuple = [('Andrew','Andrew@gmail.com','20'),('Jim',"Jim@gmail.com",'12'),("Sarah","Sarah@gmail.com",'43'),("Jim","Jim@gmail.com",'15'),("Andrew","Andrew@gmail.com",'56')]
result = []
for item in mytuple:
    if item[1] not in result:
        result.append(item[1]) 
print result

<强>输出:

['Andrew@gmail.com', 'Jim@gmail.com', 'Sarah@gmail.com']

答案 5 :(得分:0)

项目的顺序是否重要?很多建议的答案使用set来唯一 - 如果列表。如果订单不重要,这是好的,适当的,高效的。如果订单确实很重要,您可以使用OrderedDict执行类似集合的唯一化,同时保留订单。

# test data
mytuple = [('Andrew','Andrew@gmail.com','20'),('Jim',"Jim@gmail.com",'12'),("Sarah","Sarah@gmail.com",'43'),("Jim","Jim@gmail.com",'15'),("Andrew","Andrew@gmail.com",'56')]

from collections import OrderedDict
emails = list(OrderedDict((t[1], 1) for t in mytuple).keys())
print emails

产量:

['Andrew@gmail.com', 'Jim@gmail.com', 'Sarah@gmail.com']

<强>更新

根据iCodez的建议,重申答案:

from collections import OrderedDict
emails = list(OrderedDict.fromkeys(t[1] for t in mytuple).keys())