【问题标题】:How to find an intersection given a list of lists that contain dictionaries如何在给定包含字典的列表列表的情况下找到交集
【发布时间】:2020-07-27 15:59:03
【问题描述】:

现在我正在使用https://www.geeksforgeeks.org/python-find-common-elements-in-list-of-lists/上的方法2,代码如下:

# Python3 code to demonstrate  
# common element extraction form N lists  
# using map() + intersection() 
  
# initializing list of lists 
test_list = [[2, 3, 5, 8], [2, 6, 7, 3], [10, 9, 2, 3]] 
  
# printing original list 
print ("The original list is : " + str(test_list)) 
  
# common element extraction form N lists 
# using map() + intersection() 
res = list(set.intersection(*map(set, test_list))) 
  
# printing result 
print ("The common elements from N lists : " + str(res)) 

原来的列表是:[[2, 3, 5, 8], [2, 6, 7, 3], [10, 9, 2, 3]]

N 个列表中的共同元素:[2, 3]

我想做同样的事情,除了使用

test_list = [[dict2,dict3,dict5,dict8],[dict2,dict6,dict7,dict3],[dict10,dict9,dict2,dict3]]

在哪里,

原来的名单是:

test_list = [[dict2,dict3,dict5,dict8],[dict2,dict6,dict7,dict3],[dict10,dict9,dict2,dict3]]

N 个列表中的共同元素:[dict2, dict3]

【问题讨论】:

  • 你可以保留你原来的解决方案,你只需要使用字典的ids来代替集合操作。

标签: python list algorithm dictionary types


【解决方案1】:

dicts 是不可散列的,因此set(a_dict) 不起作用。

定义


class my_dict(dict):

     @classmethod
     def freeze(cls, obj):
          if isinstance(obj, dict):
              obj_with_frozen_values = {k: cls.freeze(v) for k, v in obj.items()}
              # sort on keys to get one specific order
              return frozenset(sorted(obj_with_frozen_values.items(), key=lambda k: k[0]))
          if isinstance(obj, (set, tuple, list)):
              obj_type = str(type(obj))
              frozen_obj = tuple([cls.freeze(v) for v in obj])
              return frozenset((obj_type, frozen_obj))  # add extra info obj type
          return obj

     def __hash__(self):
          return hash(self.freeze(self))

(这应该注意内部值是 dict/lists 等)

然后将所有字典映射到 my_dict。希望这能解决问题。

【讨论】:

    【解决方案2】:

    您不能使用set 技术,因为集合的元素需要是可散列的,而字典则不是。您可以在 dicts 之间进行相等比较测试,但您必须“手动”执行此操作。这是一个示例解决方案,您可以通过从第一个子列表的副本开始获取交集,然后删除不在剩余子列表中的项目。

    dict2 = {"foo": [2]}
    dict3 = {"foo": 3}
    dict5 = {"bar": 5}
    dict6 = {"bar": []}
    dict7 = {"bar": 7}
    dict8 = {"bar": 8}
    dict9 = {"baz": 9}
    dict10 = {"quux": 10}
    
    test_list = [[dict2,dict3,dict5,dict8],
                 [dict2,dict6,dict7,dict3],
                 [dict10,dict9,dict2,dict3]]
    
    answer = test_list[0].copy()
    for lst in test_list[1:]:
        remove_indices = [i for i, item in enumerate(answer) if item not in lst]
        for i in remove_indices[::-1]:
            answer.pop(i)
    
    print(answer)
    

    打印:

    [{'foo': [2]}, {'foo': 3}]
    

    【讨论】:

      【解决方案3】:

      集合需要可散列的项目,但字典不需要。 让我们定义一个自定义的 dict 类哈希。 (我参考这篇文章。python set of objects with custom hash behavior

      import json
      
      class DictItem(dict):
          """custome dict class hashable"""
          def __hash__(self):
              return hash(frozenset(json.dumps(self, sort_keys=True)))
          
      dict2 = DictItem({"foo": [2]})
      dict3 = DictItem({"foo": 3})
      dict5 = DictItem({"bar": 5})
      dict6 = DictItem({"bar": []})
      dict7 = DictItem({"bar": 7})
      dict8 = DictItem({"bar": 8})
      dict9 = DictItem({"baz": 9})
      dict10 = DictItem({"quux": 10})
      
      test_list = [[dict2,dict3,dict5,dict8],
                   [dict2,dict6,dict7,dict3],
                   [dict10,dict9,dict2,dict3]]
      res = list(set.intersection(*map(set, test_list))) 
        
      # printing result 
      print ("The common elements from N lists : " + str(res)) 
      

      【讨论】:

      • 这似乎只适用于长度为 2 的字典
      • 您可以将其应用于任何类型的字典。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-06
      相关资源
      最近更新 更多