【问题标题】:Grab unique tuples in python list, irrespective of order在 python 列表中获取唯一的元组,无论顺序如何
【发布时间】:2016-06-28 18:39:17
【问题描述】:

我有一个 python 列表:

[ (2,2),(2,3),(1,4),(2,2), etc...]

我需要的是某种功能,可以将其简化为独特的组件...在上面的列表中:

[ (2,2),(2,3),(1,4) ]

numpy unique 并没有完全做到这一点。我可以想办法做到这一点——将我的元组转换为数字[22,23,14,etc.],找到唯一的,然后从那里开始工作……但我不知道复杂性是否会失控。有没有一个函数可以做我想要对元组做的事情?


下面是演示问题的代码示例:

 import numpy as np

 x = [(2,2),(2,2),(2,3)]
 y = np.unique(x)

返回:y: [2 3]

这是演示修复的解决方案的实现:

 x = [(2,2),(2,2),(2,3)]
 y = list(set(x))

返回 y: [(2,2),(2,3)]

【问题讨论】:

  • 顺序重要吗?
  • 不过,您要“找到唯一的” 数字,只需用元组尝试一下。为什么你认为会有所不同?
  • @jonrsharpe,在元组上使用 numpy 运行它;没用。
  • 那么您为什么不提供该代码的minimal reproducible example 以及比“没有工作” 更具体的问题描述?
  • 你得到答案的事实并没有使这个问题的第一次修订变得更好,这并不意味着你在写下一个问题时不能改进;请在未来展示你的工作。

标签: python list numpy duplicates


【解决方案1】:

如果顺序无关紧要

如果结果的顺序不重要,您可以将列表转换为集合(因为元组是可散列的)并将集合转换回列表:

>>> l = [(2,2),(2,3),(1,4),(2,2)]
>>> list(set(l))
[(2, 3), (1, 4), (2, 2)]

如果订单很重要

(更新)

从 CPython 3.6(或任何 Python 3.7 版本)开始,常规字典会记住它们的插入顺序,因此您可以简单地发出。

>>> l = [(2,2),(2,3),(1,4),(2,2)]
>>> list(dict.fromkeys(l))
[(2, 2), (2, 3), (1, 4)]

(旧答案)

如果顺序很重要,过滤重复项的规范方法是:

>>> seen = set()
>>> result = []
>>> for item in l:
...     if item not in seen:
...         seen.add(item)
...         result.append(item)
... 
>>> result
[(2, 2), (2, 3), (1, 4)]

最后,稍微慢一点,也有点hackish,你可以把OrderedDict当作一个有序集合来滥用:

>>> from collections import OrderedDict
>>> OrderedDict.fromkeys(l).keys() # or list(OrderedDict.fromkeys(l)) if using a version where keys() does not return a list
[(2, 2), (2, 3), (1, 4)]

【讨论】:

    【解决方案2】:

    使用set 将删除重复项,然后您可以从中创建一个list

    >>> list(set([ (2,2),(2,3),(1,4),(2,2) ]))
    [(2, 3), (1, 4), (2, 2)]
    

    【讨论】:

      【解决方案3】:

      你可以这样做

      y = np.unique(x, axis=0)
      z = [] 
      for i in y:
         z.append(tuple(i))
      

      原因是 numpy 将元组列表解释为二维数组。通过设置axis = 0,您会要求numpy不要展平数组并返回唯一的行。

      【讨论】:

      • 这会吐出一个二维数组,给出你想要的。如果您想要一个元组列表,请考虑我的答案的编辑版本。
      • 我认为这更符合我使用 np.unique 的目的
      • 不错的解决方案,可以使用列表理解使其更短:[tuple(i) for i in np.unique(x, axis=0)]
      • 如果我们的原始列表是这样的呢? [(1, [[3, 3, 3], 3, 3]), (2, [[4, 4, 4], 4, 4]), (3, [[5, 5, 5], 5 , 5]), (1, [[3, 3, 3], 3, 3])]?
      【解决方案4】:

      set() 将删除所有重复项,然后您可以将其放回列表中:

      unique = list(set(mylist))
      

      但是,使用 set() 会终止您的订购。如果顺序很重要,您可以使用列表推导来检查该值是否已经存在于列表的前面:

      unique = [v for i,v in enumerate(mylist) if v not in mylist[:i]]
      

      不过,这个解决方案有点慢,所以你可以这样做:

      unique = []
      for tup in mylist:
          if tup not in unique:
              unique.append(tup)
      

      【讨论】:

      • 第二种解决方案对于大型列表来说很慢,因为list.__contains__ 是 O(n)。
      • 除了查看是否在列表中之外,还有什么方法可以查看之前是否使用过某些东西?
      • 是的,存储已在集合中看到的内容:) - 不同之处在于该集合具有 O(1) 成员资格测试。
      猜你喜欢
      • 2013-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-10
      • 1970-01-01
      • 2023-04-11
      • 2017-07-28
      相关资源
      最近更新 更多