到目前为止我的代码非常难看:
orig = [(1,2),(1,3),(2,3),(3,3)]
previous_elem = []
unique_tuples = []
for tuple in orig:
if tuple[0] not in previous_elem:
unique_tuples += [tuple]
previous_elem += [tuple[0]]
assert unique_tuples == [(1,2),(2,3),(3,3)]
必须有更多的pythonic解决方案。
答案 0 :(得分:8)
如果您不关心为重复项返回哪个元组,您可以随时将列表转换为字典并返回:
>>> orig = [(1,2),(1,3),(2,3),(3,3)]
>>> list(dict(orig).items())
[(1, 3), (2, 3), (3, 3)]
如果您想要返回 第一个 元组回合,您可以将列表反转两次并使用OrderedDict
,如下所示:
>>> from collections import OrderedDict
>>> orig = [(1,2),(1,3),(2,3),(3,3)]
>>> new = list(OrderedDict(orig[::-1]).items())[::-1]
[(1, 2), (2, 3), (3, 3)]
这些并不是最有效的解决方案(,如果这非常重要),但它们确实可以制作出很好的惯用语。
注意速度的差异,如果您不关心返回哪个元组,第一个选项效率更高:
>>> import timeit
>>> setup = '''
orig = [(1,2),(1,3),(2,3),(3,3)]
'''
>>> print (min(timeit.Timer('(list(dict(orig).items()))', setup=setup).repeat(7, 1000)))
0.0015771419037069459
与
相比>>>setup = '''
orig = [(1,2),(1,3),(2,3),(3,3)]
from collections import OrderedDict
'''
>>> print (min(timeit.Timer('(list(OrderedDict(orig[::-1]).items())[::-1])',
setup=setup).repeat(7, 1000)))
0.024554947372323
根据这些速度测试,第一个选项快了近15倍。
尽管如此,Saksham's answer也是O(n)
并且效率明智地破坏了这些词典方法:
>>> setup = '''
orig = [(1,2),(1,3),(2,3),(3,3)]
newlist = []
seen = set()
def fun():
for (a, b) in orig:
if not a in seen:
newlist.append((a, b))
seen.add(a)
return newlist
'''
>>> print (min(timeit.Timer('fun()', setup=setup).repeat(7, 1000)))
0.0004833390384996095
答案 1 :(得分:2)
如果您希望包含特定键的第一个键始终是最终列表中显示的键:
list(reversed(collections.OrderedDict( reversed([(1,2),(1,3),(2,3),(3,3)])).items()))
结果是:
[(1, 2), (2, 3), (3, 3)]
答案 2 :(得分:1)
如果您不希望存储其他数据结构,则时间复杂度为O(n^2)
,如评论中所述:
orig = [(1,2),(1,3),(2,3),(3,3)]
newlist = []
for (a, b) in orig:
if not any(x == a for x, y in newlist):
newlist.append((a, b))
print newlist # prints [(1, 2), (2, 3), (3, 3)]
一点点簿记可以将其减少到线性时间:
orig = [(1,2),(1,3),(2,3),(3,3)]
newlist = []
seen = set()
for (a, b) in orig:
if not a in seen:
newlist.append((a, b))
seen.add(a)
print newlist # prints [(1, 2), (2, 3), (3, 3)]