假设有以下的列表:
['a','b','a']
#or
[1,2,2,2,3,4,5,6,6,6,6]
现你想去除列表中重复的项,得到:
['a','b']
# or
[1,2,3,4,5,6]
如何快速移除列表中重复项呢?这里写了几种实现方法,并做了简单速度测试,发现它们之间居然有好几十倍的差距。
当然这些方法还有一个非常重要的区别在于它们的输出结果是否能够依旧保留原本的顺序( order preserving)。
比如:uniqify([5,2,2,3])==[5,2,3]
def f1(seq):
# not order preserving
set = {}
map(set.__setitem__, seq, [])
return set.keys()
def f2(seq):
# order preserving
checked = []
for e in seq:
if e not in checked:
checked.append(e)
return checked
def f3(seq):
# Not order preserving
keys = {}
for e in seq:
keys[e] = 1
return keys.keys()
def f4(seq):
# order preserving
noDupes = []
[noDupes.append(i) for i in seq if not noDupes.count(i)]
return noDupes
def f5(seq, idfun=None):
# order preserving
if idfun is None:
def idfun(x): return x
seen = {}
result = []
for item in seq:
marker = idfun(item)
# in old Python versions:
# if seen.has_key(marker)
# but in new ones:
if marker in seen: continue
seen[marker] = 1
result.append(item)
return result
def f6(seq):
# Not order preserving
set = Set(seq)
return list(set)
测试结果如下:
* f2 13.24
* f4 11.73
* f5 0.37
f1 0.18
f3 0.17
f6 0.19
(* order preserving)
从测试结果来看,f5是最优的,不仅因为其速度,以及其具有“顺序保留”的功能,还有一个重要的原因是它可以支持如下扩展:
>>> a=list('ABeeE')>>> f5(a)
['A','B','e','E']
>>> f5(a, lambda x: x.lower())
['A','B','e']