如何从列表中删除重复项,同时保持顺序?使用集合删除重复项会破坏原始顺序。 是否有内置的或python的习语?
当前回答
不使用导入模块或集的解决方案:
text = "ask not what your country can do for you ask what you can do for your country"
sentence = text.split(" ")
noduplicates = [(sentence[i]) for i in range (0,len(sentence)) if sentence[i] not in sentence[:i]]
print(noduplicates)
给输出:
['ask', 'not', 'what', 'your', 'country', 'can', 'do', 'for', 'you']
其他回答
这里有一个简单的方法:
list1 = ["hello", " ", "w", "o", "r", "l", "d"]
sorted(set(list1 ), key=list1.index)
输出如下:
["hello", " ", "w", "o", "r", "l", "d"]
在CPython 3.6+(以及从Python 3.7+开始的所有其他Python实现)中,字典是有序的,因此从可迭代对象中删除重复项同时保持其原始顺序的方法是:
>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
在Python 3.5及以下版本(包括Python 2.7)中,使用OrderedDict。我的计时表明,这是Python 3.5的各种方法中最快和最短的(当它获得C实现时;在3.5之前,它仍然是最清晰的解决方案,尽管不是最快的)。
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
就地方法
这个方法是二次的,因为我们对列表中的每个元素都有一个线性查找(由于del,我们必须加上重新排列列表的代价)。
也就是说,如果我们从列表的末尾开始,并向原点前进,删除出现在其左侧子列表中的每一项,就有可能在原地操作
这个想法在代码中很简单
for i in range(len(l)-1,0,-1):
if l[i] in l[:i]: del l[i]
实现的简单测试
In [91]: from random import randint, seed
In [92]: seed('20080808') ; l = [randint(1,6) for _ in range(12)] # Beijing Olympics
In [93]: for i in range(len(l)-1,0,-1):
...: print(l)
...: print(i, l[i], l[:i], end='')
...: if l[i] in l[:i]:
...: print( ': remove', l[i])
...: del l[i]
...: else:
...: print()
...: print(l)
[6, 5, 1, 4, 6, 1, 6, 2, 2, 4, 5, 2]
11 2 [6, 5, 1, 4, 6, 1, 6, 2, 2, 4, 5]: remove 2
[6, 5, 1, 4, 6, 1, 6, 2, 2, 4, 5]
10 5 [6, 5, 1, 4, 6, 1, 6, 2, 2, 4]: remove 5
[6, 5, 1, 4, 6, 1, 6, 2, 2, 4]
9 4 [6, 5, 1, 4, 6, 1, 6, 2, 2]: remove 4
[6, 5, 1, 4, 6, 1, 6, 2, 2]
8 2 [6, 5, 1, 4, 6, 1, 6, 2]: remove 2
[6, 5, 1, 4, 6, 1, 6, 2]
7 2 [6, 5, 1, 4, 6, 1, 6]
[6, 5, 1, 4, 6, 1, 6, 2]
6 6 [6, 5, 1, 4, 6, 1]: remove 6
[6, 5, 1, 4, 6, 1, 2]
5 1 [6, 5, 1, 4, 6]: remove 1
[6, 5, 1, 4, 6, 2]
4 6 [6, 5, 1, 4]: remove 6
[6, 5, 1, 4, 2]
3 4 [6, 5, 1]
[6, 5, 1, 4, 2]
2 1 [6, 5]
[6, 5, 1, 4, 2]
1 5 [6]
[6, 5, 1, 4, 2]
In [94]:
这里有一些替代选项:http://www.peterbe.com/plog/uniqifiers-benchmark
最快的一个:
def f7(seq):
seen = set()
seen_add = seen.add
return [x for x in seq if not (x in seen or seen_add(x))]
为什么要赋值。添加到seen_add而不是只调用see . Add ?Python是一种动态语言,解析可见。每次迭代添加比解析一个局部变量代价更大。观察。Add可能会在迭代之间发生更改,而运行时还不够聪明,无法排除这种情况。为了安全起见,它必须每次检查对象。
如果您计划在同一个数据集上大量使用这个函数,那么使用一个有序集可能会更好:http://code.activestate.com/recipes/528878/
O(1)每次操作的插入、删除和成员检查。
(小额外注意:see .add()总是返回None,所以以上值只是作为一种尝试更新集合的方式,而不是逻辑测试的组成部分。)
你可以引用一个列表推导式,因为它是由符号'_[1]'构建的。例如,下面的函数通过引用列表推导式对元素列表进行惟一化,而不改变它们的顺序。
def unique(my_list):
return [x for x in my_list if x not in locals()['_[1]']]
演示:
l1 = [1, 2, 3, 4, 1, 2, 3, 4, 5]
l2 = [x for x in l1 if x not in locals()['_[1]']]
print l2
输出:
[1, 2, 3, 4, 5]
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录