【问题标题】:How to make lists contain only distinct element in Python? [duplicate]python - 如何使列表仅包含Python中的不同元素? [复制]
【发布时间】:2011-05-26 11:21:33
【问题描述】:

我在 Python 中有一个列表,我怎样才能使它的值唯一?

【问题讨论】:

标签: python


【解决方案1】:

Python中集合的特点是集合中的数据项 是无序的,不允许重复。如果您尝试将数据项添加到已包含该数据项的集合中,Python 会简单地忽略它。

>>> l = ['a', 'a', 'bb', 'b', 'c', 'c', '10', '10', '8','8', 10, 10, 6, 10, 11.2, 11.2, 11, 11]
>>> distinct_l = set(l)
>>> print(distinct_l)
set(['a', '10', 'c', 'b', 6, 'bb', 10, 11, 11.2, '8'])

【讨论】:

    【解决方案2】:

    字典理解怎么样?

    >>> mylist = [3, 2, 1, 3, 4, 4, 4, 5, 5, 3]
    
    >>> {x:1 for x in mylist}.keys()
    [1, 2, 3, 4, 5]
    

    编辑 对于@Danny 的评论:我最初的建议并没有让钥匙保持有序。如果您需要对键进行排序,请尝试:

    >>> from collections import OrderedDict
    
    >>> OrderedDict( (x,1) for x in mylist ).keys()
    [3, 2, 1, 4, 5]
    

    通过元素的第一次出现来保持元素的顺序(未经广泛测试)

    【讨论】:

    • 这不会保留顺序 - 字典顺序(和设置顺序)由散列算法而不是插入顺序决定。不过,我不确定使用 OrderedDict 类型的字典理解的效果。
    • @DannyStaple 是的。如果需要有序输出,我添加了一个使用 OrderedDict 和生成器的示例。
    【解决方案3】:

    我举个例子给你解释一下:

    如果你有 Python 列表

    >>> randomList = ["a","f", "b", "c", "d", "a", "c", "e", "d", "f", "e"]
    

    并且您想从中删除重复项。

    >>> uniqueList = []
    
    >>> for letter in randomList:
        if letter not in uniqueList:
            uniqueList.append(letter)
    
    >>> uniqueList
    ['a', 'f', 'b', 'c', 'd', 'e']
    

    这是您可以从列表中删除重复项的方法。

    【讨论】:

    • +1 因为它是唯一适用于不可散列但确实具有 eq 函数的类型(如果您的类型是可散列的,请使用其他解决方案之一) .请注意,对于非常大的列表,它会很慢。
    • 除非在某些特殊情况下如 Claude 解释的那样,否则这个性能最差:O(n^2)
    【解决方案4】:

    单线并保持秩序

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

    虽然你需要

    from collections import OrderedDict
    

    【讨论】:

    • 另一种形式是:OrderedDict.fromkeys(my_list).keys()
    • @DannyStaple:在 python 2 中有效,但在 python 3 中,它返回字典键的视图,这对于某些目的可能没问题,但不支持例如索引。
    • 最初的一个班轮可以工作。另一种形式返回一个 odict_keys 类型,它对此不太有用 - 但仍然可以转换为列表。
    【解决方案5】:

    在保留顺序的同时删除重复项的最简单方法是使用collections.OrderedDict(Python 2.7+)。

    from collections import OrderedDict
    d = OrderedDict()
    for x in mylist:
        d[x] = True
    print d.iterkeys()
    

    【讨论】:

      【解决方案6】:

      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? print(和 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'),并且不检查第二个参数,因为它已经知道答案,并且只有当两个参数都为真时才返回真。

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

      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))
      

      【讨论】:

      • 某种内部辅助函数(代码中有一个错误,第 2 行应该是 _f 而不是 _f10,感谢发现)
      【解决方案7】:

      如果列表的所有元素都可以用作字典键(即它们都是可散列的),这通常会更快。 Python Programming FAQ

      d = {}
      for x in mylist:
          d[x] = 1
      mylist = list(d.keys())
      

      【讨论】:

        【解决方案8】:

        为了保持顺序:

        l = [1, 1, 2, 2, 3]
        result = list()
        map(lambda x: not x in result and result.append(x), l)
        result
        # [1, 2, 3]
        

        【讨论】:

        • 在python 3.4中返回一个空列表!!!
        【解决方案9】:

        来自http://www.peterbe.com/plog/uniqifiers-benchmark

        def f5(seq, idfun=None):  
            # order preserving
            if idfun is None:
                def idfun(x): return x
            seen = {}
            result = []
            for item in seq:
                marker = idfun(item)
                # in old Python versions:
                # if seen.has_key(marker)
                # but in new ones:
                if marker in seen: continue
                seen[marker] = 1
                result.append(item)
            return result
        

        【讨论】:

        • 使用 set for seen 而不是 dict 有意义吗?
        • 在 Python 中,set 和 dicts 是使用哈希表构建的,因此它们在这种情况下可以互换。它们都提供相同的操作(限制重复)并且都具有相同的运行时间。
        • 这个比较慢,generator版本快很多
        【解决方案10】:

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

        my_list = list(set(my_list))
        

        这样做的一个缺点是它不会保留订单。您可能还想首先考虑使用集合而不是列表是否是一种更好的数据结构。

        【讨论】:

        • 我错了,或者使用 python3k 值将被保留,因为现在设置已排序?
        • @Ant 字典键顺序是从 Python 3.6 中保留的,但它说“这个新实现的顺序保留方面被认为是实现细节,不应依赖”。由于它们都基于哈希,我认为 set 是相同的,但没有提到,所以显然不是:docs.python.org/3.6/whatsnew/3.6.html
        • 保留顺序和功能方式:在[23]: from functools import reduceIn [24]: reduce(lambda acc,elem: acc+[elem] if not elem in acc else acc , [2,1,2,3,3,3,4,5], [])Out[24]: [2, 1, 3, 4, 5]
        猜你喜欢
        • 1970-01-01
        • 2012-09-30
        • 2021-02-20
        • 2017-11-17
        • 1970-01-01
        • 2022-12-11
        • 2022-08-19
        • 2015-04-09
        • 2019-02-03
        相关资源
        最近更新 更多