如何从列表中删除重复项,同时保持顺序?使用集合删除重复项会破坏原始顺序。 是否有内置的或python的习语?


当前回答

使用_sorted_ a numpy数组的相对有效方法:

b = np.array([1,3,3, 8, 12, 12,12])    
numpy.hstack([b[0], [x[0] for x in zip(b[1:], b[:-1]) if x[0]!=x[1]]])

输出:

array([ 1,  3,  8, 12])

其他回答

借用Haskell为列表定义nub函数时使用的递归思想,这将是一种递归方法:

def unique(lst):
    return [] if lst==[] else [lst[0]] + unique(filter(lambda x: x!= lst[0], lst[1:]))

例如:

In [118]: unique([1,5,1,1,4,3,4])
Out[118]: [1, 5, 4, 3]

我对不断增长的数据大小进行了尝试,看到了次线性的时间复杂度(不是确定的,但建议这对于普通数据应该没问题)。

In [122]: %timeit unique(np.random.randint(5, size=(1)))
10000 loops, best of 3: 25.3 us per loop

In [123]: %timeit unique(np.random.randint(5, size=(10)))
10000 loops, best of 3: 42.9 us per loop

In [124]: %timeit unique(np.random.randint(5, size=(100)))
10000 loops, best of 3: 132 us per loop

In [125]: %timeit unique(np.random.randint(5, size=(1000)))
1000 loops, best of 3: 1.05 ms per loop

In [126]: %timeit unique(np.random.randint(5, size=(10000)))
100 loops, best of 3: 11 ms per loop

我还认为有趣的是,这可以很容易地通过其他运算推广到唯一性。是这样的:

import operator
def unique(lst, cmp_op=operator.ne):
    return [] if lst==[] else [lst[0]] + unique(filter(lambda x: cmp_op(x, lst[0]), lst[1:]), cmp_op)

例如,你可以传入一个函数,它使用舍入到同一个整数的概念,就像它是“相等”的唯一性目的,像这样:

def test_round(x,y):
    return round(x) != round(y)

那么unique(some_list, test_round)将提供列表中唯一的元素,其中唯一性不再意味着传统的相等性(这是通过使用任何类型的基于集或基于字典键的方法来解决这个问题),而是意味着对于每个元素可能舍入的整数K,只取第一个舍入到K的元素,例如:

In [6]: unique([1.2, 5, 1.9, 1.1, 4.2, 3, 4.8], test_round)
Out[6]: [1.2, 5, 1.9, 4.2, 3]
sequence = ['1', '2', '3', '3', '6', '4', '5', '6']
unique = []
[unique.append(item) for item in sequence if item not in unique]

unique→[1、(2)、(3)、(6)、(4)、(5)]

from itertools import groupby
[ key for key,_ in groupby(sortedList)]

这个列表甚至不需要排序,充分条件是相等的值被分组在一起。

编辑:我假设“保持顺序”意味着列表实际上是有序的。如果不是这样,那么MizardX的解决方案是正确的。

社区编辑:然而,这是“将重复的连续元素压缩为单个元素”的最优雅的方法。

l = [1,2,2,3,3,...]
n = []
n.extend(ele for ele in l if ele not in set(n))

一个生成器表达式,它使用集合的O(1)查找来确定是否在新列表中包含元素。

x = [1, 2, 1, 3, 1, 4]

# brute force method
arr = []
for i in x:
  if not i in arr:
    arr.insert(x[i],i)

# recursive method
tmp = []
def remove_duplicates(j=0):
    if j < len(x):
      if not x[j] in tmp:
        tmp.append(x[j])
      i = j+1  
      remove_duplicates(i)

      

remove_duplicates()