什么是确保列表中所有元素不同的最pythonic方法?

Nat*_*man 8 python list unique

我在Python中有一个列表,我作为程序的一部分生成.我有一个强烈的假设,即这些都是不同的,我用断言来检查.

这就是我现在这样做的方式:

如果有两个要素:

try:
    assert(x[0] != x[1])
except:
    print debug_info
    raise Exception("throw to caller")
Run Code Online (Sandbox Code Playgroud)

如果有三个:

try:
    assert(x[0] != x[1])
    assert(x[0] != x[2])
    assert(x[1] != x[2])
except:
    print debug_info
    raise Exception("throw to caller")
Run Code Online (Sandbox Code Playgroud)

如果我必须用四个元素来做这件事,我会发疯的.

有没有更好的方法来确保列表中的所有元素都是唯一的?

Eli*_*ria 26

也许是这样的:

if len(x) == len(set(x)):
    print "all elements are unique"
else:
    print "elements are not unique"
Run Code Online (Sandbox Code Playgroud)

  • 您可以将它们首先存储在一个集合中,以确保它们都是唯一的.或者将它们存储在一个集合中,但在添加到集合之前检查成员资格.但是,如果您无法控制输入格式,这肯定有效. (2认同)
  • 为什么这对于这个目的很重要.我想要做的就是在删除重复项后查看列表是否具有相同数量的元素. (2认同)

Ale*_*lli 18

最流行的答案是O(N)(好! - )但是,正如@Paul和@Mark指出的那样,它们要求列表的项目是可以清除的.@Paul和@Mark提出的不可用项目的方法都是一般的,但需要O(N平方) - 即很多.

如果您的列表的项目不可清除但是具有可比性,那么您可以做得更好......这里的方法总是尽可能快地在列表的项目的性质下工作.

import itertools

def allunique(L):
  # first try sets -- fastest, if all items are hashable
  try:
    return len(L) == len(set(L))
  except TypeError:
    pass
  # next, try sort -- second fastest, if items are comparable
  try:
    L1 = sorted(L)
  except TypeError:
    pass
  else:
    return all(len(list(g))==1 for k, g in itertools.groupby(L1))
  # fall back to the slowest but most general approach
  return all(v not in L[i+1:] for i, L in enumerate(L))
Run Code Online (Sandbox Code Playgroud)

这是O(N)在可行的情况下(所有项目都可以清洗),O(N log N)作为最常见的后备(一些项目不可用,但都是可比较的),O(N平方)不可避免(某些项目不可取,例如dicts,和一些不可比的,例如复数).

这段代码的灵感来自于伟大的蒂姆·彼得斯(Tim Peters)的一个古老的食谱,它实际上产生了一系列独特的物品(而且到目前为止set还没有 - 它必须使用dict......! - ),但基本上面临同样的问题.


Ark*_*ady 7

这个怎么样:

if len(x) != len(set(x)):
    raise Exception("throw to caller")
Run Code Online (Sandbox Code Playgroud)

这假设元素是x可以清除的.