【问题标题】:Python - How to calculate equal parts of two dictionaries?Python - 如何计算两个字典的相等部分?
【发布时间】:2010-10-12 21:47:24
【问题描述】:

我在组合或计算这两个字典的公共/相等部分时遇到问题。在我的字典中,值是列表:

d1 = {0:['11','18','25','38'], 
      1:['11','18','25','38'], 
      2:['11','18','25','38'], 
      3:['11','18','25','38']}

d2 = {0:['05','08','11','13','16','25','34','38','40', '43'], 
      1:['05', '08', '09','13','15','20','32','36','38', '40','41'], 
      2:['02', '08', '11', '13', '18', '20', '22','33','36','39'], 
      3:['06', '11', '12', '25', '26', '27', '28', '30', '31', '37']}

我想检查“d2”并知道是否有来自“d1”的数字。如果有的话,我想用新数据更新其中一个或接收第三个字典“d3”,其中只有“d1”和“d2”中相同/相等的值,例如:

d3 = {0:['11','25','38'], 1:['38'], 2:['11','18'], 3:['11','25']} 

谁能帮我解决这个问题?

我的错,我忘了说得更具体。我正在寻找 Python 中的解决方案。

【问题讨论】:

  • 请指定您的语言,或者如果您不关心。您的示例可以被视为某些现有语言的伪代码或文字;最好知道你的期望。
  • 您基本上是在要求对集合交集进行一些迭代。这是非常依赖于语言的。请指定相关语言。
  • 我的错我忘了说得更具体。我正在寻找 Python 中的解决方案。
  • d3 的答案对我来说也是错误的。
  • 我添加了一个 Python 标签,因为从我的评论中可以清楚地看出他在谈论 Python。

标签: python list dictionary merge


【解决方案1】:

在伪代码中:

Dictionary d3 = new Dictionary()
for (i = 0 to min(d1.size(), d2.size()))
{
  element shared = getSharedElements(d1[i], d2[i]);
  d3.store(i, shared);
}

function getsharedElements(array e1, array e2)
{
  element e3 = new element();
  for (int i = 0 to e1.length)
  {
    if (e2.contains(e1[i]))
    {
      e3.add[e1[i]];
    }
  }
  return e3;
}

【讨论】:

  • 呵呵,Python其实比伪代码更简洁! “Python 是可执行的伪代码”,确实!
  • 这是在原帖提到python之前发布的。
【解决方案2】:

假设这是 Python,你想要:

dict((x, set(y) & set(d1.get(x, ()))) for (x, y) in d2.iteritems())

生成结果字典“d3”。

Python 3.0+ 版本

>>> d3 = {k: list(set(d1.get(k,[])).intersection(v)) for k, v in d2.items()}
{0: ['11', '25', '38'], 1: ['38'], 2: ['11', '18'], 3: ['11', '25']}

上述版本(以及 Python 2.x 版本)允许空交叉点,因此在一般情况下需要额外的过滤:

>>> d3 = {k: v for k, v in d3.items() if v}

将以上内容合二为一:

d3 = {}
for k, v in d2.items():
    # find common elements for d1 & d2
    v3 = set(d1.get(k,[])).intersection(v)
    if v3: # whether there are common elements
       d3[k] = list(v3) 

[编辑:我创建了这个帖子社区 wiki,以便人们可以根据需要对其进行改进。我承认如果你不习惯在 Python 中阅读这类东西,它可能会有点难以阅读。]

【讨论】:

  • 我使用了你的解决方案,但出现错误:TypeError: 'int' object is not iterable 你能帮我解决这个问题吗?
  • 对不起,有一个错字。您想使用“d2.iteritems()”来获取那里的项目列表。
  • 返回:{0: set(['11', '25', '38']), 1: set(['38']), 2: set(['11' , '18']), 3: set(['11', '25'])} 所以非常接近。
  • dict((x, list(set(y) & set(d1.get(x, ())))) for (x, y) in d2.iteritems()) 使它返回列表的字典,如果您愿意,可以不设置。
  • 令人印象深刻,但我不认为聪明的单行词特别 Pythonic。
【解决方案3】:

问题归结为确定两个条目之间的共同元素。 (要获得所有条目的结果,只需将代码包含在所有条目的循环中。)此外,看起来每个条目都是一个集合(即它没有重复的元素)。因此,您需要做的就是找到这些元素之间的集合交集。许多语言提供了这样做的方法或功能。例如在 C++ 中使用 set 容器和 set_intersection 函数。这比其他人建议的将一组中的每个元素与另一组中的每个元素进行比较要有效得多。

【讨论】:

    【解决方案4】:

    如果我们可以假设 d1 和 d2 具有相同的键:

    d3 = {}
    for k in d1.keys():
        intersection = set(d1[k]) & set(d2[k])
        d3[k] = [x for x in intersection]
    

    否则,如果我们不能假设,那就有点混乱了:

    d3 = {}
    for k in set(d1.keys() + d2.keys()):
        intersection = set(d1.get(k, [])) & set(d2.get(k, []))
        d3[k] = [x for x in intersection]
    

    编辑:考虑到 cmets 的新版本。这个只检查 d1 和 d2 共有的键,这似乎是发帖人要问的。

    d3 = {}
    for k in set(d1.keys()) & set(d2.keys()):
        intersection = set(d1[k]) & set(d2[k])
        d3[k] = list(intersection)
    

    【讨论】:

    • @SilentGhost,这是为什么呢?需要详细说明吗?或者你编写一个更 Pythonic 的代码。
    • 我赞成约翰的回答,尽管我自己写的是:{i: list(set(j) & set(d1.get(i, []))) for i , j in d2.items()}
    • @SilentGhost,为什么这样更好?
    • @SilentGhost,这不是一个真正的论点;这只是一个主观的断言。我认为您的版本很糟糕,因为需要努力将其拆开并理解它。如果我在生产代码中找到它,我会很生气。
    • 有什么理由不使用“d3[k]= list(intersection)”?
    【解决方案5】:

    提供更易读的解决方案:

    d3= {}
    for common_key in set(d1) & set(d2):
        common_values= set(d1[common_key]) & set(d2[common_key])
        d3[common_key]= list(common_values)
    

    建议后编辑:

    如果您只想要具有至少一个公共值项的键:

    d3= {}
    for common_key in set(d1) & set(d2):
        common_values= set(d1[common_key]) & set(d2[common_key])
        if common_values:
            d3[common_key]= list(common_values)
    

    如果顺序和重复不重要,您可以将 d1 和 d2 值保留为集合而不是列表。

    【讨论】:

    • +1:为了可读性。虽然我会删除 common_ 前缀并用明确的 intersection() 调用替换 &(但这是一个口味问题)。
    • 顺便说一句,common_values 在一般情况下可能是一个空集。 OP 询问“有一些”,即 all(d3.values()) 必须为 True。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 2019-09-20
    • 1970-01-01
    • 2021-09-14
    相关资源
    最近更新 更多