在python中,如何合并具有相似键的字典元素?

时间:2018-09-06 15:10:20

标签: python

在git中,我运行git shortlog -sn以在回购中构建作者及其提交的列表。在某些情况下,多位作者实际上是同一个人,但是具有不同的大小写或名字,而不是名字+姓氏。示例:

$ git shortlog -sn
100 John Doe
 50 john

我在Python脚本中使用subprocess执行此命令,最终将其解析为字典。例如,它是这样的:

>>> users = {"John Doe": 100, "john": 50}
>>> users
{'John Doe': 100, 'john': 50}

我需要遍历这些内容并在键上运行一个正则表达式,以比较两个名称是否以相同的名字开头(无论大小写),并且:

  1. 组合键以显示不同的作者姓名
  2. 对每个元素的提交(值)求和。所以最终结果应该是:

    {'John Doe, john': 150}
    

为此,我可能会提出一些粗略的实现,但是它不是很pythonic。寻找一个干净和简单的实现。

2 个答案:

答案 0 :(得分:0)

一个简单的解决方案就是这样

data = {"John Doe": 100, "john": 50}
new_data = {}
for name, amount in data.items():
    first_name = name.lower().split(" ")[0]
    (current_names, current_amount) = new_data.get(first_name, [[], 0])
    current_names.append(name)
    current_amount += amount
    new_data[first_name] = [current_names, current_amount]

new_data
#=> {'john': [['john', 'John Doe'], 150]}

names_and_data = {}
for names, amount in new_data.values():
    joined_names = ", ".join(names)
    names_and_data[joined_names] = amount

names_and_data
#=> {'john, John Doe': 150}

答案 1 :(得分:0)

摘要

from collections import defaultdict

dd = defaultdict(list)
for u in users:
    k = u.split()[0].lower()
    dd[k].append(u)

merged = {','.join(names): sum(users[name] for name in names)
          for firstname, names in dd.items()}

说明

这种方法使用defaultdict来收集所有相同的不区分大小写的名字。

In [184]: from collections import defaultdict

In [185]: dd = defaultdict(list)

In [186]: for u in users:
     ...:     k = u.split()[0].lower()
     ...:     dd[k].append(u)
     ...:

In [187]: dd
Out[187]: defaultdict(list, {'john': ['john', 'John Doe']})

然后您可以使用此查找表创建合并格式,如下所示

In [188]: merged = {','.join(names): sum(users[name] for name in names)
    ...:            for firstname, names in dd.items()}

In [189]: merged
Out[189]: {'john,John Doe': 150}

为了美观,您还可以在join

中添加空格
In [188]: merged = {', '.join(names): sum(users[name] for name in names)
    ...:            for firstname, names in dd.items()}

In [189]: merged
Out[189]: {'john, John Doe': 150}

请注意,这不会区分

jonathan
john
jon
jon-dawg

@wim暗示这是一个复杂得多的问题,需要一些自定义正则表达式