【问题标题】:Take unique values out of a list with unhashable elements [duplicate]从具有不可散列元素的列表中取出唯一值[重复]
【发布时间】:2019-03-04 13:24:29
【问题描述】:

所以我有以下列表:

test_list = ['Hallo', 42, [1, 2], 42, 3 + 2j, 'Hallo', 'Hello', [1, 2], [2, 3], 3 + 2j, 42] 

现在我想从列表中获取唯一值并将它们打印在屏幕上。我尝试过使用 set 函数,但由于 [1,2] 和 [2,3] 值在名单。我尝试使用 append 和 extend 函数,但还没有提出解决方案。

期望: ['你好', 42, [1,2], (3+2j), '你好', [2,3]]

def unique_list(a_list): 
    a = set(a_list)
    print(a)
a_list = ['Hallo', 42, [1, 2], 42, 3 + 2j, 'Hallo', 'Hello', [1, 2], [2, 3], 3 + 2j, 42]
print(unique_list(a_list))   

【问题讨论】:

  • 您能否详细说明您的代码“不起作用”的原因?你期待什么,实际发生了什么?如果您遇到异常/错误,请发布它发生的行和异常/错误详细信息。请edit这些详细信息,否则我们可能无法提供帮助。如果没有看到您的原始代码,我们将不知道如何对您现有的代码库进行更改。请发minimal reproducible example,并详细说明需要修改的地方。
  • 编辑我的帖子感谢您通知我。
  • 列表不能是集合的元素(或作为字典的键作为重复的注释)。

标签: python python-3.x


【解决方案1】:

如果列表包含不可散列的元素,请使用 repr 创建一个可散列键,并与集合一起使用:

def unique_list(a_list):
    seen = set()
    for x in a_list:
        key = repr(x)
        if key not in seen:
            seen.add(key)
            print(x)

【讨论】:

    【解决方案2】:

    您可以使用仅附加新元素的简单 for 循环:

    test_list = ['Hallo', 42, [1, 2], 42, 3 + 2j, 'Hallo', 'Hello', [1, 2], [2, 3], 3 + 2j, 42]
    new_list = []
    
    for item in test_list:
        if item not in new_list:
            new_list.append(item)
    
    print(new_list)
    # ['Hallo', 42, [1, 2], (3+2j), 'Hello', [2, 3]]
    

    【讨论】:

      【解决方案3】:

      要从非哈希列表中获取唯一项目,可以通过等价进行分区,这是一种二次方法,因为它将每个项目与每个分区中的项目进行比较,如果不等于其中一个它为该项目创建一个新分区,然后获取每个分区的第一个项目。

      如果某些项目是可散列的,则可以将等价分区限制为仅不可散列的项目。并通过一组喂剩下的物品。

      import itertools
      
      def partition(L):
          parts = []
          for item in L:
              for part in parts:
                  if item == part[0]:
                     part.append(item)
                     break
              else:
                  parts.append([item])
          return parts
      
      def unique(L):
          return [p[0] for p in partition(L)]
      

      未经测试。

      【讨论】:

        【解决方案4】:

        在线性时间内解决此问题的一种方法是使用诸如pickle 之类的序列化程序对项目进行序列化,以便可以将诸如列表之类的不可散列对象添加到集合中以进行重复数据删除,但是由于集合在 Python 中是无序的,而您显然如果希望输出按照原始插入顺序,您可以改用dict.fromkeys

        import pickle
        list(map(pickle.loads, dict.fromkeys(map(pickle.dumps, test_list))))
        

        因此,给定您的示例输入,这将返回:

        ['Hallo', 42, [1, 2], (3+2j), 'Hello', [2, 3]]
        

        请注意,如果您使用的 Python 3.6 或更早版本无法保证 dicts 的键顺序,您可以使用 collections.OrderedDict 代替 dict

        【讨论】:

        • 感谢您的回答。我有点局限于python的基本功能:while,for,if,append等。所以我不知道有这样的功能,但我会看看它并调试它更好地理解它。
        【解决方案5】:

        您可以在 O(n^2) 中运行的常规 for 循环中执行此操作。

        def unique_list(a_list):
            orig = a_list[:]               # shallow-copy original list to avoid modifying it
            uniq = []                      # start with an empty list as our result
            while(len(orig) > 0):          # iterate through the original list
                uniq.append(orig[0])       # for each element, append it to the unique elements list
                while(uniq[-1] in orig):   # then, remove all occurrences of that element in the original list
                    orig.remove(uniq[-1])
            return uniq                    # finally, return the list of unique elements in order of first occurrence in the original list
        

        可能还有一种方法可以将其转换为列表理解,这会更优雅,但我目前无法弄清楚。如果每个元素都是可散列的,您可以使用 set 方法,这样会更容易。

        【讨论】:

        • 这在时间复杂度上绝对是二次的而不是线性的。
        • 感谢您的评论。这似乎是一个我可以在更多练习后提出的解决方案。
        猜你喜欢
        • 2012-06-02
        • 2018-05-15
        • 1970-01-01
        • 2013-06-12
        • 2014-04-20
        • 2021-06-02
        • 2013-08-14
        • 2020-11-15
        • 2018-05-27
        相关资源
        最近更新 更多