【问题标题】:Delete Tuples in more dimensional list if same如果相同,则删除更多维列表中的元组
【发布时间】:2018-11-19 09:59:52
【问题描述】:

我有一个元组列表:

[[[('p', 'u'), ('r', 'w')], [('t', 'q')]], [[('p', 'u'), ('r', 'w')], [('v', 'q')]], [[('p', 'u'), ('r', 'w')], [('t', 's')]], [[('p', 'u'), ('r', 'w')], [('v', 's')]], [[('p', 'w'), ('r', 'u')], [('t', 'q')]], [[('p', 'w'), ('r', 'u')], [('v', 'q')]], [[('p', 'w'), ('r', 'u')], [('t', 's')]], [[('p', 'w'), ('r', 'u')], [('v', 's')]], [[('r', 'u'), ('p', 'w')], [('t', 'q')]], [[('r', 'u'), ('p', 'w')], [('v', 'q')]], [[('r', 'u'), ('p', 'w')], [('t', 's')]], [[('r', 'u'), ('p', 'w')], [('v', 's')]], **[[('r', 'w'), ('p', 'u')], [('t', 'q')]]**, [[('r', 'w'), ('p', 'u')], [('v', 'q')]], [[('r', 'w'), ('p', 'u')], [('t', 's')]], [[('r', 'w'), ('p', 'u')], [('v', 's')]]]

但现在例如元素[[('p','u'),('r','w')], [('t','q')]]

[[('r','w'),('p','u')], [('t','q')]]相同,在列表中标记为

所以在列表中我有 16 个元素,其中每个元素都是双倍的。

现在,我想删除重复项,因为我只剩下前八个元素了。

太天真了,我试过了

[[list(y) for y in set([tuple(set(x)) for x in doublegammas1])]]

但在这里,他说:

TypeError: unhashable type: 'list'

所以我的问题:

如何扩展列表理解,使其适用于更多维度的列表?

【问题讨论】:

    标签: python tuples double list-comprehension


    【解决方案1】:

    列表不可散列,元组可散列。然后,您需要获取这些元组的set。但是在这些元组中,你想忽略顺序。但是集合元组是不可散列的,所以你需要使用frozenset对象的元组:

    uniques = {tuple(map(frozenset, i)) for i in doublegammas1}
    
    print(uniques)
    
    {(frozenset({('p', 'w'), ('r', 'u')}), frozenset({('t', 'q')})),
     (frozenset({('p', 'w'), ('r', 'u')}), frozenset({('v', 'q')})),
     (frozenset({('p', 'w'), ('r', 'u')}), frozenset({('v', 's')})),
     (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('t', 's')})),
     (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('t', 'q')})),
     (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('v', 'q')})),
     (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('v', 's')})),
     (frozenset({('p', 'w'), ('r', 'u')}), frozenset({('t', 's')}))}
    

    然后您可以通过 itertools unique_everseen recipe 应用此功能,也可以在 3rd 方库中以 toolz.uniquemore_itertools.unique_everseen 的形式使用:

    from more_itertools import unique_everseen
    
    def uniquekey(x):
        return tuple(map(frozenset, x))
    
    res = list(unique_everseen(doublegammas1, key=uniquekey))
    
    print(res)
    
    [[[('p', 'u'), ('r', 'w')], [('t', 'q')]],
     [[('p', 'u'), ('r', 'w')], [('v', 'q')]],
     [[('p', 'u'), ('r', 'w')], [('t', 's')]],
     [[('p', 'u'), ('r', 'w')], [('v', 's')]],
     [[('p', 'w'), ('r', 'u')], [('t', 'q')]],
     [[('p', 'w'), ('r', 'u')], [('v', 'q')]],
     [[('p', 'w'), ('r', 'u')], [('t', 's')]],
     [[('p', 'w'), ('r', 'u')], [('v', 's')]]]
    

    输入数据

    # input data
    doublegammas1 = [[[('p', 'u'), ('r', 'w')], [('t', 'q')]],
                     [[('p', 'u'), ('r', 'w')], [('v', 'q')]],
                     [[('p', 'u'), ('r', 'w')], [('t', 's')]],
                     [[('p', 'u'), ('r', 'w')], [('v', 's')]],
                     [[('p', 'w'), ('r', 'u')], [('t', 'q')]],
                     [[('p', 'w'), ('r', 'u')], [('v', 'q')]],
                     [[('p', 'w'), ('r', 'u')], [('t', 's')]],
                     [[('p', 'w'), ('r', 'u')], [('v', 's')]],
                     [[('r', 'u'), ('p', 'w')], [('t', 'q')]],
                     [[('r', 'u'), ('p', 'w')], [('v', 'q')]],
                     [[('r', 'u'), ('p', 'w')], [('t', 's')]],
                     [[('r', 'u'), ('p', 'w')], [('v', 's')]],
                     [[('r', 'w'), ('p', 'u')], [('t', 'q')]],
                     [[('r', 'w'), ('p', 'u')], [('v', 'q')]],
                     [[('r', 'w'), ('p', 'u')], [('t', 's')]],
                     [[('r', 'w'), ('p', 'u')], [('v', 's')]]]
    

    【讨论】:

      【解决方案2】:

      可变对象(例如列表或集合)不能是集合的成员。你可以使用一个frozenset,它是不可变的。

      main_list = [[[('p', 'u'), ('r', 'w')], [('t', 'q')]],
                   [[('p', 'u'), ('r', 'w')], [('v', 'q')]],
                   [[('p', 'u'), ('r', 'w')], [('t', 's')]],
                   [[('p', 'u'), ('r', 'w')], [('v', 's')]],
                   [[('p', 'w'), ('r', 'u')], [('t', 'q')]],
                   [[('p', 'w'), ('r', 'u')], [('v', 'q')]],
                   [[('p', 'w'), ('r', 'u')], [('t', 's')]],
                   [[('p', 'w'), ('r', 'u')], [('v', 's')]],
                   [[('r', 'u'), ('p', 'w')], [('t', 'q')]],
                   [[('r', 'u'), ('p', 'w')], [('v', 'q')]],
                   [[('r', 'u'), ('p', 'w')], [('t', 's')]],
                   [[('r', 'u'), ('p', 'w')], [('v', 's')]],
                   [[('r', 'w'), ('p', 'u')], [('t', 'q')]],
                   [[('r', 'w'), ('p', 'u')], [('v', 'q')]],
                   [[('r', 'w'), ('p', 'u')], [('t', 's')]],
                   [[('r', 'w'), ('p', 'u')], [('v', 's')]]]
      
      main_set = set(tuple(frozenset(innermost_list) for innermost_list in sublist) for sublist in main_list)
      
      from pprint import pprint
      pprint(main_set)
      

      输出:

      {(frozenset({('r', 'u'), ('p', 'w')}), frozenset({('t', 'q')})),
       (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('v', 'q')})),
       (frozenset({('r', 'u'), ('p', 'w')}), frozenset({('v', 'q')})),
       (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('t', 's')})),
       (frozenset({('r', 'u'), ('p', 'w')}), frozenset({('t', 's')})),
       (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('v', 's')})),
       (frozenset({('r', 'u'), ('p', 'w')}), frozenset({('v', 's')})),
       (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('t', 'q')}))}
      

      要转换回嵌套列表的原始结构:

      new_list = [[list(frozen) for frozen in subtuple] for subtuple in main_set]
      pprint(new_list)
      

      输出:

      [[[('r', 'u'), ('p', 'w')], [('t', 'q')]],
       [[('p', 'u'), ('r', 'w')], [('v', 'q')]],
       [[('r', 'u'), ('p', 'w')], [('v', 'q')]],
       [[('p', 'u'), ('r', 'w')], [('t', 's')]],
       [[('r', 'u'), ('p', 'w')], [('t', 's')]],
       [[('p', 'u'), ('r', 'w')], [('v', 's')]],
       [[('r', 'u'), ('p', 'w')], [('v', 's')]],
       [[('p', 'u'), ('r', 'w')], [('t', 'q')]]]
      

      更新:

      一种从输入数据中就地删除重复项的解决方案。

      unique = []
      
      for item in main_list[:]:
          frozen_item = frozenset(frozenset(innermost_list) for innermost_list in item)
          if frozen_item not in unique:
              unique.append(frozen_item)
          else:
              main_list.remove(item)
      

      【讨论】:

      • 非常感谢! :) 那么你是怎么学到这些东西的?有教程吗?
      • 这个解决方案的优点是它只使用了 2 行。缺点是您通过散列解开它,然后在new_list 中再次将其重新组合在一起,从而重复逻辑(列表的构造方式)。
      • @jpp 我添加了一个似乎可行的就地解决方案(不过更多的是作为练习,因为原始问题要求理解而不是循环)。
      • @7t7Studios,为什么不使用set?即unique = set()unique.add(frozen_item)。顺便说一句,这与我的解决方案中的unique_everseen 相同。
      • 是的,基本上是一样的,除了需要导入一个 3rd 方模块。顺便说一句,你知道他们为什么给seen.add() 取别名吗?这样更快吗?无论如何,感谢链接库,那里有很多有趣的东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-22
      相关资源
      最近更新 更多