【问题标题】:Remove duplicate dict based on key and value in dict根据字典中的键和值删除重复的字典
【发布时间】:2020-10-20 08:21:00
【问题描述】:

我有一个结构数据:

matches = [
                {
                    "15477084": [1]
                },
                {
                    "360418": [2]
                },
                {
                    "15477084": [1]
                },
                {
                    "15477084": [3,4]
                }
            ]

我想检查键中的键和值是否重复,我将其删除。如果 key 和 value 有很多不同的值,我会把它结合起来。

我希望我的结果像:

matches = [
                {
                    "15477084": [1,3,4]
                },
                {
                    "360418": [2]
                }
            ]

这是我的代码:

new_matches = []

for j in matches:
    newdict = dict()
    for key,value in j.items():
        if key in newdict.keys():
            if value not in newdict[key]:
                newdict[key].append(value)
                new_matches.append(newdict)
        else:
            newdict[key] = value
            new_matches.append(newdict)

但我的结果是错误的(我的结果与数据匹配开始相同)。我不知道为什么我的结果是错误的。

【问题讨论】:

  • 为什么15477084[1,2,3] 而不是[1,1,3,4]?对于您的代码,您在每次迭代中都创建了空字典 newdict,因此 if key in newdict.keys() 将始终为 False,因此与原始输入没有区别。
  • @Chris 我已尝试将newdict 定位在循环之外for j in matches,但它不起作用。我想根据键删除重复值,所以 15477084 需要有 [1,3,4]

标签: python python-3.x list dictionary duplicates


【解决方案1】:
from collections import defaultdict

result = defaultdict(list)
for item in matches:
    for k, v in item.items():
        result[k] += v

print([{k: v} for k, v in result.items()])

输出:

[{'15477084': [1, 1, 3, 4]}, {'360418': [2]}]

编辑:使最终输出独一无二:

print([{k: list(set(v))} for k, v in result.items()])

【讨论】:

  • 感谢您的解决方案,但我想 15477084 有值 [1,3,4] 我想删除重复项
  • 你可以修改最终输出喜欢这个print([{k: list(set(v))} for k, v in result.items()])或像其他人一样在defaultdict中使用set
  • 你能解释一下为什么你添加{k: list(set(v))},数据会删除重复吗?我是一个理解python的新手。对不起,如果我的问题让你讨厌
  • set() 函数将您的数据转换为仅包含唯一项目的集合(您是正确的,没有重复项),list() 函数会将其转换回列表。
【解决方案2】:

试试这个:

from collections import defaultdict
from itertools import chain

res = defaultdict(list)

for x in matches:
    (k,) = x
    if x[k] not in res[k]:
        res[k].append(x[k])

res = {k: list(chain(*v)) for k, v in res.items()}
print(res)

输出:

{'15477084': [1, 3, 4], '360418': [2]}

【讨论】:

  • 非常感谢,但是在 `res = {k: list(chain(*v)) for k,v in res.items()} 我不明白你为什么这样做。你能帮我解释一下吗
  • res dict 中的值是我正在从中制作平面 lsit 的列表列表
  • chain.from_iterable(v) 代替chain(*v) 可能会更好。
【解决方案3】:

因为我喜欢 pandas,所以我提供了一种特殊的方法来解决您的问题。也许你会喜欢它。

import json
import pandas as pd


if __name__ == "__main__":
    matches = [
        {"15477084": [1]},
        {"360418": [2]},
        {"15477084": [1]},
        {"15477084": [3, 4]},
    ]
    matches_df = pd.DataFrame(matches)
    matches_df = matches_df.fillna("[]").transpose().astype(str).apply(
        lambda x: list(
            set([record for sub in x.tolist() for record in json.loads(sub)])
        ),
        axis=1,
    )
    result = matches_df.to_dict()
    print(result)

这是结果

{'15477084': [1, 3, 4], '360418': [2]}

【讨论】:

  • 这是解决我问题的新解决方案,非常感谢。
【解决方案4】:

你可以试试这个:

from collections import defaultdict

v = defaultdict(set)

for dict_values in matches:
    for key, value in sorted(dict_values.items()):
        print(key)
        for i in value:
            v[key].add(i)

输出:

defaultdict(set, {'15477084': {1, 3, 4}, '360418': {2}})

【讨论】:

    【解决方案5】:

    defaultdict 可以在这里提供帮助

    from collections import defaultdict
    
    res_matches = defaultdict(list)
    for i in matches:
        key, value = list(i.keys())[0], list(i.values())[0]
        to_add = set(value).difference(set(res_matches[key]))
        if to_add:
            res_matches[key].extend(to_add)
    print(dict(res_matches))
    

    输出

    {'15477084': [1, 3, 4], '360418': [2]}
    

    【讨论】:

      【解决方案6】:

      您的程序的问题是每次迭代都会创建 newdict 并且它不会有任何键值对,因此语句(如果 newdict.keys() 中的键)总是为假,所以 else 语句将被执行,它会将匹配列表中的字典追加到 new_matches 中。

      还有语句(如果 value 不在 newdict[key] 中),这里的 value 是一个列表,newdict[key] 也将是一个列表(如果你解决了上述问题),所以你正在比较两个列表.即)[1] == [3,4] 这不是真的。相反,您应该迭代列表中任何一个中的每个值,并将其与另一个列表进行比较。

      我已经通过解决您程序中的两个问题提供了解决方案。

      matches = [
                      {
                          "15477084": [1]
                      },
                      {
                          "360418": [2]
                      },
                      {
                          "15477084": [1]
                      },
                      {
                          "15477084": [3,4]
                      }
                  ]
                  
                  
      new_matches = []
      
      for j in matches:
          newdict = dict()
          for key,value in j.items():
              if len(new_matches) != 0:
                  for k in new_matches:
                      if key in k.keys():
                          for i in value:
                              if i not in k[key]:
                                  k[key].append(i)
                          break
      
                      else:
                          newdict[key] = value
                          new_matches.append(newdict)                 
              else:
                  newdict[key] = value
                  new_matches.append(newdict)
      
      print(new_matches)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-06
        • 2020-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多