【问题标题】:Remove duplicates in python list but remember the index删除python列表中的重复项但记住索引
【发布时间】:2016-04-06 19:33:54
【问题描述】:

如何删除列表中的重复项,保持项目的原始顺序并记住列表中任何项目的第一个索引?

例如,从[1, 1, 2, 3] 中删除重复项会产生[1, 2, 3],但我需要记住索引[0, 2, 3]

我使用的是 Python 2.7。

【问题讨论】:

    标签: python list python-2.7


    【解决方案1】:

    使用enumerate 来跟踪索引并使用集合来跟踪所见元素:

    l = [1, 1, 2, 3]
    inds = []
    seen = set()
    for i, ele in enumerate(l):
        if ele not in seen:
            inds.append(i)
        seen.add(ele)
    

    如果你想要两者:

    inds = []
    seen = set()
    for i, ele in enumerate(l):
        if ele not in seen:
            inds.append((i,ele))
        seen.add(ele)
    

    或者,如果您希望两者都在不同的列表中:

    l = [1, 1, 2, 3]
    inds, unq = [],[]
    seen = set()
    for i, ele in enumerate(l):
        if ele not in seen:
            inds.append(i)
            unq.append(ele)
        seen.add(ele)
    

    到目前为止,使用集合是最好的方法:

    In [13]: l = [randint(1,10000) for _ in range(10000)]     
    
    In [14]: %%timeit                                         
    inds = []
    seen = set()
    for i, ele in enumerate(l):
        if ele not in seen:
            inds.append((i,ele))
        seen.add(ele)
       ....: 
    100 loops, best of 3: 3.08 ms per loop
    
    In [15]: timeit  OrderedDict((x, l.index(x)) for x in l)
    1 loops, best of 3: 442 ms per loop
    
    In [16]: l = [randint(1,10000) for _ in range(100000)]      
    In [17]: timeit  OrderedDict((x, l.index(x)) for x in l)
    1 loops, best of 3: 10.3 s per loop
    
    In [18]: %%timeit                                       
    inds = []
    seen = set()
    for i, ele in enumerate(l):
        if ele not in seen:
            inds.append((i,ele))
        seen.add(ele)
       ....: 
    10 loops, best of 3: 22.6 ms per loop
    

    所以对于100k 元素10.3 秒与22.6 ms,如果您尝试使用像[randint(1,100000) for _ in range(100000)] 这样具有较少欺骗性的更大的东西,您将有时间阅读一本书。创建两个列表稍微慢一些,但仍然比使用 list.index 快几个数量级。

    如果你想一次获取一个值,你可以使用生成器函数:

    def yield_un(l):
        seen = set()
        for i, ele in enumerate(l):
            if ele not in seen:
                yield (i,ele)
            seen.add(ele)
    

    【讨论】:

    • 很好的解释与时间比较...从来没有这样的区别.. :-O
    【解决方案2】:

    我会稍微不同地解决这个问题,并使用OrderedDict 以及列表index 方法将返回项目的最低索引这一事实。

    >>> from collections import OrderedDict
    >>> lst = [1, 1, 2, 3]
    >>> d = OrderedDict((x, lst.index(x)) for x in lst)
    >>> d
    OrderedDict([(1, 0), (2, 2), (3, 3)]
    

    如果您需要列表(删除重复项)和索引,您可以简单地发出:

    >>> d.keys()
    [1, 2, 3]
    >>> d.values()
    [0, 2, 3]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-22
      • 2016-06-26
      • 2011-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多