我想从下面的列表中获得唯一的值:

['nowplaying', 'PBS', 'PBS', 'nowplaying', 'job', 'debate', 'thenandnow']

我需要的输出是:

['nowplaying', 'PBS', 'job', 'debate', 'thenandnow']

这段代码工作:

output = []
for x in trends:
    if x not in output:
        output.append(x)
print(output)

有更好的解决方案吗?


当前回答

要从列表中获得唯一的值,请使用下面的代码:

trends = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
output = set(trends)
output = list(output)

重要的是: 如果列表中的任何项都不是可哈希的,上述方法将不起作用,这是可变类型的情况,例如list或dict。

trends = [{'super':u'nowplaying'}, u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
output = set(trends)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  TypeError: unhashable type: 'dict'

这意味着你必须确保趋势列表总是只包含可哈希项,否则你必须使用更复杂的代码:

from copy import deepcopy

try:
    trends = [{'super':u'nowplaying'}, [u'PBS',], [u'PBS',], u'nowplaying', u'job', u'debate', u'thenandnow', {'super':u'nowplaying'}]
    output = set(trends)
    output = list(output)
except TypeError:
    trends_copy = deepcopy(trends)
    while trends_copy:
        trend = trends_copy.pop()
        if trends_copy.count(trend) == 0:
            output.append(trend)
print output

其他回答

def setlist(lst=[]):
   return list(set(lst))

你的输出变量是什么类型?

Python集是你所需要的。像这样声明输出:

output = set()  # initialize an empty set

你已经准备好使用output.add(elem)添加元素,并确保它们是唯一的。

警告:集合不保留列表的原始顺序。

删除重复项的选项可能包括以下通用数据结构:

集合:无序的,唯一的元素 有序集:有序的、唯一的元素

下面是关于如何在Python中快速获取其中一个的总结。

鉴于

from collections import OrderedDict


seq = [u"nowplaying", u"PBS", u"PBS", u"nowplaying", u"job", u"debate", u"thenandnow"]

Code

选项1 -一组(无序):

list(set(seq))
# ['thenandnow', 'PBS', 'debate', 'job', 'nowplaying']
    

Python没有有序集,但这里有一些模拟有序集的方法。

选项2 -一个OrderedDict(插入顺序):

list(OrderedDict.fromkeys(seq))
# ['nowplaying', 'PBS', 'job', 'debate', 'thenandnow']

选项3 -字典(插入顺序),Python 3.6+中的默认值。在这篇文章中可以看到更多细节:

list(dict.fromkeys(seq))
# ['nowplaying', 'PBS', 'job', 'debate', 'thenandnow']

注意:列出的元素必须是可哈希的。在这篇博客文章中查看后一个示例的详细信息。此外,请参阅R. Hettinger关于相同技术的帖子;保序字典是从他早期的一个实现扩展而来的。参见更多关于总排序的信息。

从List中获取唯一元素

mylist = [1,2,3,4,5,6,6,7,7,8,8,9,9,10]

从集合中使用简单的逻辑-集合是唯一的项目列表

mylist=list(set(mylist))

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

使用简单逻辑

newList=[]
for i in mylist:
    if i not in newList:
        newList.append(i)

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

使用pop方法 ->pop删除最后一个或索引项,并显示给用户。视频

k=0
while k < len(mylist):
    if mylist[k] in mylist[k+1:]:
        mylist.pop(mylist[k])
    else:
        k=k+1

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

使用Numpy

import numpy as np
np.unique(mylist)

In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

参考

如果我们需要保持元素的顺序,那么这样怎么样:

used = set()
mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = [x for x in mylist if x not in used and (used.add(x) or True)]

还有一个使用reduce的解决方案,没有临时使用的var。

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = reduce(lambda l, x: l.append(x) or l if x not in l else l, mylist, [])

更新- 2020年12月-也许是最好的方法!

从python 3.7开始,标准字典保持插入顺序。

在3.7版更改:字典顺序保证为插入顺序。此行为是CPython 3.6版本的实现细节。

因此,这使我们能够使用dict.from_keys进行重复删除!

注意:感谢@rlat在评论中给我们这个方法!

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = list(dict.fromkeys(mylist))

在速度方面——对我来说,它足够快,足够易读,成为我最喜欢的新方法!

更新- 2019年3月

第三个解,很简洁,但有点慢,因为。index是O(n)

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = [x for i, x in enumerate(mylist) if i == mylist.index(x)]

更新- 2016年10月

另一种使用reduce的解决方案,但这次没有.append,这使得它更易于阅读和理解。

mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = reduce(lambda l, x: l+[x] if x not in l else l, mylist, [])
#which can also be writed as:
unique = reduce(lambda l, x: l if x in l else l+[x], mylist, [])

注意:请记住,我们获得的人类可读性越高,脚本的性能就越差。除了dict.from_keys方法,它是python 3.7+特有的。

import timeit

setup = "mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']"

#10x to Michael for pointing out that we can get faster with set()
timeit.timeit('[x for x in mylist if x not in used and (used.add(x) or True)]', setup='used = set();'+setup)
0.2029558869980974

timeit.timeit('[x for x in mylist if x not in used and (used.append(x) or True)]', setup='used = [];'+setup)
0.28999493700030143

# 10x to rlat for suggesting this approach!   
timeit.timeit('list(dict.fromkeys(mylist))', setup=setup)
0.31227896199925453

timeit.timeit('reduce(lambda l, x: l.append(x) or l if x not in l else l, mylist, [])', setup='from functools import reduce;'+setup)
0.7149233570016804

timeit.timeit('reduce(lambda l, x: l+[x] if x not in l else l, mylist, [])', setup='from functools import reduce;'+setup)
0.7379565160008497

timeit.timeit('reduce(lambda l, x: l if x in l else l+[x], mylist, [])', setup='from functools import reduce;'+setup)
0.7400134069976048

timeit.timeit('[x for i, x in enumerate(mylist) if i == mylist.index(x)]', setup=setup)
0.9154880290006986

回复评论

因为@莫妮卡问了一个关于“这是怎么工作的?”的好问题。献给每一个有问题的人。我将尝试更深入地解释这是如何工作的,以及这里发生了什么巫术;)

所以她首先问:

我试图理解为什么unique = [used.append(x) for x in mylist if x not in used]是不工作的。

它确实起作用了

>>> used = []
>>> mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
>>> unique = [used.append(x) for x in mylist if x not in used]
>>> print used
[u'nowplaying', u'PBS', u'job', u'debate', u'thenandnow']
>>> print unique
[None, None, None, None, None]

问题是我们只是在唯一的变量中没有得到想要的结果,而只是在使用的变量中。这是因为在列表理解过程中.append会修改所使用的变量并返回None。

因此,为了将结果放入唯一变量中,并且如果x未被使用,则仍然使用与.append(x)相同的逻辑,我们需要将这个.append调用移动到列表推导式的右侧,并在左侧返回x。

但如果我们太天真了,就这样:

>>> unique = [x for x in mylist if x not in used and used.append(x)]
>>> print unique
[]

我们将得不到任何回报。

同样,这是因为.append方法返回None,它会在我们的逻辑表达式上显示如下外观:

x not in used and None

这基本上总是:

当使用x时,结果为False, 当x未被使用时,计算结果为None。

在这两种情况下(False/None),这将被视为假值,我们将得到一个空列表作为结果。

但是当x不被使用时,为什么这个值为None呢?有人可能会问。

这是因为Python的短路操作符就是这样工作的。

表达式x和y首先求x的值;如果x为false,则其值为 返回;否则,计算y,结果值为 返回。

因此,当x未被使用时(即当它为True时),下一部分或表达式将被计算(using .append(x)),并返回它的值(None)。

但这就是我们想要的,为了从具有重复项的列表中获得唯一的元素,我们希望仅当它们第一次遇到时才将它们追加到新列表中。

因此,我们希望只在x未被使用时才对used。append(x)求值,如果有办法将None值转换为真值就可以了,对吧?

是的,这就是第二种短路操作者发挥作用的地方。

表达式x或y首先求x的值;如果x为真,它的值为 返回;否则,计算y,结果值为 返回。

我们知道.append(x)总是假的,所以如果我们只是在它旁边加上一个或,我们总是会得到下一个部分。这就是为什么我们写:

x not in used and (used.append(x) or True)

因此,我们可以求use .append(x)的值并得到True结果,只有当表达式的第一部分(x未被使用)为True时。

类似的方式可以在第二种方法中看到reduce方法。

(l.append(x) or l) if x not in l else l
#similar as the above, but maybe more readable
#we return l unchanged when x is in l
#we append x to l and return l when x is not in l
l if x in l else (l.append(x) or l)

我们去的地方:

将x追加到l并在x不在l时返回l。由于or语句,. Append被求值并在此之后返回l。 当x在l中时,返回l原封不动