我有3个字典列表,我想合并和排序。如果同一个_id
的dict不止一个,则应删除副本,但应将count_enabled
和count_disabled
的值添加(总和)到剩余的一个。这些列表可能有也可能没有重复,长度不同
Foo = [
{'_id': 'core.system', 'count_enabled': 9, 'count_disabled': 0},
{'_id': 'core.system', 'count_enabled': 0, 'count_disabled': 0},
{'_id': 'core.private_channel', 'count_enabled': 4, 'count_disabled': 0}]
Bar = [
{'_id': 'core.admin', 'count_enabled': 9, 'count_disabled': 0},
{'_id': 'core.colors', 'count_enabled': 0, 'count_disabled': 0},
{'_id': 'core.system', 'count_enabled': 0, 'count_disabled': 0}]
Baz = [
{'_id': 'core.system', 'count_enabled': 0, 'count_disabled': 0},
{'_id': 'core.whois', 'count_enabled': 9, 'count_disabled': 0}]
这是我到目前为止所做的:
data = []
for i in [Foo,Bar,Baz]:
for j in i:
data.append({'module':j['_id'], 'count_enabled' : j['count_enabled'], 'count_disabled': j['count_disabled']})
sort = sorted(data, key=itemgetter('module'))
我也将_id
重命名为module
,但这不是很重要,data
已正确排序,唯一剩下的就是删除重复项并添加其值。
答案 0 :(得分:1)
除了排序,我认为将所有词典合并到最终列表中可以使用下面的代码完成。
我基本上为唯一字典条目创建了final_list
。
对于dict
的每个list
,我遍历final_dict
中的字典条目(final_list
)。如果我找到包含当前final_dict
的{{1}},我会对这些值进行求和,然后突破内部for循环以继续_id
中的下一个dict
。
如果我在任何list
中找不到_id
,我会将该词典附加到最终列表中。
final_dict
答案 1 :(得分:0)
我有点不清楚你最终希望在这里生产什么。但我会假设它是一个排序的dicts列表,其中每个dict只有三个键。我假设你有理由,但这是一个非常尴尬的结构。为什么不关键_id
/ module
?
类似的东西:
enabled = dict()
disabled = dict()
for i in (Foo, Bar, Baz):
enabled[i[module]] = enabled.get(i[module], 0) + i['count_enabled']
disabled[i[module]] = disabled.get(i[module], 0) + i['count_disabled']
results = [{'module': m, 'count_enabled': enabled[m], 'count_disabled': disabled[m]} for m in sorted(enabled.keys())]
答案 2 :(得分:0)
或者,您可以使用Python的集合,特别是defaultdict
和reduce()
来合并字典。
import collections
import functools
# Group the dictionaries by '_id'.
records = collections.defaultdict(list)
for record in [*Foo, *Bar, *Baz]:
id = record['_id']
record.pop('_id', None)
records[id].append(record)
# Combine the dictionaries from each group.
data = []
for key, value in records.items():
data.append({ **{'_id': key, },
**dict(functools.reduce(
lambda x, y: x.update(y),
[collections.Counter(x) for x in value]
))}
)
print(data)
请务必注意,运行上面的代码会导致删除任何具有非零值的键。如果要保持键具有非零值,可以使用以下代码替换最后一个for
循环。
data = []
for key, value in records.items():
combined_values = collections.Counter()
for d in value:
combined_values.update(d)
data.append({ **{'_id': key, }, **combined_values )}
)