我有一个包含字典的列表 (List[Dict, Dict, ...]
) ,我想基于两个键来统一列表,但我想保留的值字典中的另一个键,通过在我想保留的键中列出一个列表来确保我不会丢失它。我正在使用 Python 作为代码。确切地说,如果它对 Python 3.x 有任何意义。
假设我有以下包含三个键的字典列表:number
、favorite
和color
。我想使用键 number
和 favorite
统一列表元素。但是对于具有相同值 number
和 favorite
的字典,我想在键 color
下添加一个列表以确保我将所有 color
用于 number
和 favorite
的相同组合。此列表也应该是唯一的,因为对于相同的组合,它不需要重复的 color
。但是,如果最终结果中的关键颜色只有一个元素,则它应该是一个字符串而不是列表。
lst = [
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': False, 'color': 'green'},
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'}]
使用前面提到的 uniqify,我会得到以下结果:
lst = [
{'number': 1, 'favorite': False, 'color': {'red', 'green'}},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'},
]
请注意,只有一个 red
实例,其中 number
是 1
并且 favorite
是 False
即使它在被统一之前在列表中出现了两次。另请注意,当第二个字典中的键 color
只有一个元素时,它是一个字符串而不是列表。
最佳答案
使用纯 python,您可以插入 OrderedDict
以保留插入顺序:
from collections import OrderedDict
d = OrderedDict()
for l in lst:
d.setdefault((l['number'], l['favorite']), set()).add(l['color'])
[{'number': k[0], 'favorite': k[1], 'color': v.pop() if len(v) == 1 else v}
for k, v in d.items()]
# [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
# {'color': 'red', 'favorite': True, 'number': 1},
# {'color': 'red', 'favorite': False, 'number': 2}]
这也可以使用 pandas GroupBy
API 轻松完成:
import pandas as pd
d = (pd.DataFrame(lst)
.groupby(['number', 'favorite'])
.color
.agg(set)
.reset_index()
.to_dict('r'))
d
# [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
# {'color': {'red'}, 'favorite': True, 'number': 1},
# {'color': {'red'}, 'favorite': False, 'number': 2}]
如果需要单个元素的字符串条件,可以使用
[{'color': (lambda v: v.pop() if len(v) == 1 else v)(d_.pop('color')), **d_}
for d_ in d]
# [{'color': {'green', 'red'}, 'favorite': False, 'number': 1},
# {'color': 'red', 'favorite': True, 'number': 1},
# {'color': 'red', 'favorite': False, 'number': 2}]
关于python - 按多个键对字典列表进行分组和聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54248936/