如何在Python中创建仅包含不同元素的列表?

214 投票
10 回答
382909 浏览
提问于 2025-04-16 08:37

我在Python里有一个列表,我该怎么让里面的值变得唯一呢?

10 个回答

31

一行代码并保持顺序

list(OrderedDict.fromkeys([2,1,1,3]))

不过你需要

from collections import OrderedDict
33

修改版的 http://www.peterbe.com/plog/uniqifiers-benchmark

为了保持顺序:

def f(seq): # Order preserving
  ''' Modified version of Dave Kirby solution '''
  seen = set()
  return [x for x in seq if x not in seen and not seen.add(x)]

好吧,现在我们来看看它是怎么工作的,因为这里有点复杂,特别是这段代码 if x not in seen and not seen.add(x)

In [1]: 0 not in [1,2,3] and not print('add')
add
Out[1]: True

为什么它会返回 True?打印(以及 set.add)什么都不返回:

In [3]: type(seen.add(10))
Out[3]: <type 'NoneType'>

而且 not None == True,但是:

In [2]: 1 not in [1,2,3] and not print('add')
Out[2]: False

为什么在 [1] 中会打印 'add',而在 [2] 中却没有?看看 False and print('add'),它不会检查第二个参数,因为它已经知道答案了,只有当两个参数都为 True 时才会返回 True。

更通用的版本,更易读,基于生成器,增加了用函数转换值的能力:

def f(seq, idfun=None): # Order preserving
  return list(_f(seq, idfun))

def _f(seq, idfun=None):  
  ''' Originally proposed by Andrew Dalke '''
  seen = set()
  if idfun is None:
    for x in seq:
      if x not in seen:
        seen.add(x)
        yield x
  else:
    for x in seq:
      x = idfun(x)
      if x not in seen:
        seen.add(x)
        yield x

没有顺序(速度更快):

def f(seq): # Not order preserving
  return list(set(seq))
393

最简单的方法是先把列表转换成集合,然后再转换回列表:

my_list = list(set(my_list))

不过这样做有个缺点,就是它不会保留原来的顺序。你也可以考虑一下,直接用集合作为数据结构是否更合适,而不是用列表。

撰写回答