Python 3.x 如何在python3中按姓氏对全名字典键进行排序和分组?

Python 3.x 如何在python3中按姓氏对全名字典键进行排序和分组?,python-3.x,dictionary,grouping,Python 3.x,Dictionary,Grouping,我想按键对字典进行分类和分组。键当前是全名,但我想将所有相似的姓氏组合在一起,并组合它们的值对。输入词典摘录如下: facdict = {'Yimei Li': [' Ph.D.', 'Assistant Professor of Biostatistics', 'liy3@email.chop.edu'], 'Mingyao Li': [' Ph.D.', 'Associate Professor of Biostatistics', 'mingyao@mail.med.upenn.edu'

我想按键对字典进行分类和分组。键当前是全名,但我想将所有相似的姓氏组合在一起,并组合它们的值对。输入词典摘录如下:

facdict = {'Yimei Li': [' Ph.D.', 'Assistant Professor of Biostatistics', 'liy3@email.chop.edu'], 
'Mingyao Li': [' Ph.D.', 'Associate Professor of Biostatistics', 'mingyao@mail.med.upenn.edu'], 
'Hongzhe Li': [' Ph.D', 'Professor of Biostatistics', 'hongzhe@upenn.edu'], 
'A. Russell Localio': [' JD MA MPH MS PhD', 'Associate Professor of Biostatistics', 'rlocalio@upenn.edu']}
所需输出为:

last_name_dict = {'Li': [[' Ph.D.', 'Assistant Professor of Biostatistics', 'liy3@email.chop.edu'], [' Ph.D.', 'Associate Professor of Biostatistics', 'mingyao@mail.med.upenn.edu'], [' Ph.D', 'Professor of Biostatistics', 'hongzhe@upenn.edu']], 
'Localio': [' JD MA MPH MS PhD', 'Associate Professor of Biostatistics', 'rlocalio@upenn.edu']}
我尝试使用以下词典理解:

search = re.compile(r"([A-Z]{1}[a-z]+)")
last_name_dict = {k.replace(k, search.findall(k)[-1:][0]): v for k, v in facdict.items()}

但是,它只返回每个条目的姓氏和与之相关联的第一个值对。

字典理解只能产生单个键值对;任何重复的对都不会合并,只需替换同一键的上一个值即可

只需使用常规循环,并使用以下命令初始化外部列表:

dictionary.setdefault(key,[])
在dictionary中查找并返回该键。但是,如果尚未设置键,则在返回该对象之前,将使用第二个参数首先设置值。因此在上面的代码中,
last\u name\u dict.setdefault(…)
的返回值总是返回一个列表,因此我们可以调用
.append(…)
并添加另一个条目

如果您不介意错误的键不会出现键错误,您可以使用:

考虑到
last\u name\u dict[unknown\u key]
将创建另一个列表对象并返回该对象


如果您首先对输入的姓氏进行排序,然后使用相同的姓氏值对输入进行分组,则可以使用字典理解来实现相同的目的,但这样做效率不高。上述解决方案将输入分组为O(N)线性时间;对于10个项目,您需要10个步骤,对于100个项目,您需要100个步骤,等等。排序需要O(NlogN)准线性时间,其中10个项目需要大约33个步骤,100个项目需要大约664个步骤,等等。如果排序步骤更快,则很快不再重要,随着输入数量的增加,与不需要排序时相比,需要排序时的步骤数量增加得更快,因此最终还是会变慢。

值得指出的是,不可能进行排序。
last_name_dict = {}
for k, v in facdict.items():
    last_name = k.replace(k, search.findall(k)[-1:][0])
    last_name_dict.setdefault(last_name, []).append(v)
from collections import defaultdict

last_name_dict = defaultdict(list)
for k, v in facdict.items():
    last_name = k.replace(k, search.findall(k)[-1:][0])
    last_name_dict[last_name].append(v)