如果第一个元素是重复的,则从列表中删除元组的大多数pythonic方法

时间:2015-04-10 14:24:49

标签: python list tuples

到目前为止我的代码非常难看:

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解决方案。

3 个答案:

答案 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)]