从元组列表中删除值

3

我有一个元组列表,我只想返回其中的第二列数据,并且只返回唯一值。

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个回答

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 answer :

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

Hasan的回答:

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
尝试:
>>> unique_mytuple_new = set([k[1] for k in mytuple])
>>> unique_mytuple_new
set(['Sarah@gmail.com', 'Jim@gmail.com', 'Andrew@gmail.com'])

@user3885927,抱歉啊。我不小心拒绝了你的编辑!! - Hasan Ramezani

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

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

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循环)。
因为Python中的and执行短路评估,所以只有在x[1] not in seen返回True时,not seen.add(x[1])才会被评估。因此,该条件查看x[1]是否在集合中,如果不在,则添加它。
“not”运算符放置在“seen.add(x[1])”之前,以便在条件评估为True时将x [1]添加到集合中(set.add返回None,被视为False。not False是True)。请注意,保留HTML标签。

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

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

你实际上可以这样做:emails = OrderedDict.fromkeys(x[1] for x in mytuple).keys() - user2555451
公正的观点。在Python 2中,这很好用,我想这是我们的目标版本。但我尽量编写能够在Python 3中无缝运行的代码。在py3中,keys方法返回一个视图对象。您可以遍历它并使用它,就像使用list一样...但它不是真正的list - Jonathan Eunice
那么,可以这样写:emails = list(OrderedDict.fromkeys(x[1] for x in mytuple))。这个版本都可以运行。不过我只是提供了一个建议,你现在的代码也可以正常工作。 - user2555451
好的。答案已经更新为更简洁的表述。谢谢! - Jonathan Eunice

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