我想将两个多个dicts的列表组合成一个新的dicts列表,将新的dicts添加到最终列表中,并将这些视图添加到一起来查看'遇到的价值。
a = [{'title': 'Learning How to Program', 'views': 1,'url': '/4XvR', 'slug': 'learning-how-to-program'},
{'title': 'Mastering Programming', 'views': 3,'url': '/7XqR', 'slug': 'mastering-programming'}]
b = [{'title': 'Learning How to Program', 'views': 7,'url': '/4XvR', 'slug': 'learning-how-to-program'},
{'title': 'Mastering Programming', 'views': 2,'url': '/7XqR', 'slug': 'mastering-programming'},
{'title': 'Programming Fundamentals', 'views': 1,'url': '/93hB', 'slug': 'programming-fundamentals'}]
所需的输出是:
c = [{'title': 'Learning How to Program', 'views': 8,'url': '/4XvR', 'slug': 'learning-how-to-program'},
{'title': 'Mastering Programming', 'views': 5,'url': '/7XqR', 'slug': 'mastering-programming'},
{'title': 'Programming Fundamentals', 'views': 1,'url': '/93hB', 'slug': 'programming-fundamentals'}]
我发现Is there any pythonic way to combine two dicts (adding values for keys that appear in both)? - 但我不明白如何在我的情况下获得所需的输出,有两个多个dicts列表。
答案 0 :(得分:2)
您需要将输入词典转换为(title: count)
对,并将其用作Counter
中的键和值;然后在求和之后,您可以将它们转换回旧格式:
from collections import Counter
summed = sum((Counter({elem['title']: elem['views']}) for elem in a + b), Counter())
c = [{'title': title, 'views': counts} for title, counts in summed.items()]
演示:
>>> from collections import Counter
>>> a = [{'title': 'Learning How to Program', 'views': 1},
... {'title': 'Mastering Programming', 'views': 3}]
>>> b = [{'title': 'Learning How to Program', 'views': 7},
... {'title': 'Mastering Programming', 'views': 2},
... {'title': 'Programming Fundamentals', 'views': 1}]
>>> summed = sum((Counter({elem['title']: elem['views']}) for elem in a + b), Counter())
>>> summed
Counter({'Learning How to Program': 8, 'Mastering Programming': 5, 'Programming Fundamentals': 1})
>>> [{'title': title, 'views': counts} for title, counts in summed.items()]
[{'views': 8, 'title': 'Learning How to Program'}, {'views': 5, 'title': 'Mastering Programming'}, {'views': 1, 'title': 'Programming Fundamentals'}]
此处的目标是每个计数都有一个唯一标识符。如果您的词典更复杂,您需要将整个字典(减去计数)转换为唯一标识符,或者从字典中选择一个值作为该标识符。然后将每个标识符的视图计数加起来。
从您更新的示例中,该URL将是一个很好的标识符。这样您就可以收集视图计数 :
per_url = {}
for entry in a + b:
key = entry['url']
if key not in per_url:
per_url[key] = entry.copy()
else:
per_url[key]['views'] += entry['views']
c = per_url.values() # use list(per_url.values()) on Python 3
这只是使用字典本身(或至少是遇到的第一个字典的副本)来对视图计数求和:
>>> from pprint import pprint
>>> a = [{'title': 'Learning How to Program', 'views': 1,'url': '/4XvR', 'slug': 'learning-how-to-program'},
... {'title': 'Mastering Programming', 'views': 3,'url': '/7XqR', 'slug': 'mastering-programming'}]
>>> b = [{'title': 'Learning How to Program', 'views': 7,'url': '/4XvR', 'slug': 'learning-how-to-program'},
... {'title': 'Mastering Programming', 'views': 2,'url': '/7XqR', 'slug': 'mastering-programming'},
... {'title': 'Programming Fundamentals', 'views': 1,'url': '/93hB', 'slug': 'programming-fundamentals'}]
>>> per_url = {}
>>> for entry in a + b:
... key = entry['url']
... if key not in per_url:
... per_url[key] = entry.copy()
... else:
... per_url[key]['views'] += entry['views']
...
>>> per_url
{'/93hB': {'url': '/93hB', 'title': 'Programming Fundamentals', 'slug': 'programming-fundamentals', 'views': 1}, '/4XvR': {'url': '/4XvR', 'title': 'Learning How to Program', 'slug': 'learning-how-to-program', 'views': 8}, '/7XqR': {'url': '/7XqR', 'title': 'Mastering Programming', 'slug': 'mastering-programming', 'views': 5}}
>>> pprint(per_url.values())
[{'slug': 'programming-fundamentals',
'title': 'Programming Fundamentals',
'url': '/93hB',
'views': 1},
{'slug': 'learning-how-to-program',
'title': 'Learning How to Program',
'url': '/4XvR',
'views': 8},
{'slug': 'mastering-programming',
'title': 'Mastering Programming',
'url': '/7XqR',
'views': 5}]
答案 1 :(得分:1)
首先,您需要将输入转换为dicts,例如
b = {'Learning How to Program': 7,
'Mastering Programming': 2,
'Programming Fundamentals': 1}
之后,应用找到的解决方案,然后将其转换回dicts列表。
答案 2 :(得分:1)
这是一个简单的问题。浏览所有条目,在第一次遇到条目时复制条目,并在后续遭遇中添加视图:
summary = {}
for entry in a + b:
key = entry['url']
if key not in summary:
summary[key] = entry.copy()
else:
summary[key]['views'] += entry['views']
c = list(summary.values())
答案 3 :(得分:0)
它可能不是最pythonic的解决方案:
def coalesce(d1,d2):
combined = [i for i in d1]
for d in d2:
found = False
for itr in combined:
if itr['title'] == d['title']:
itr['views'] += d['views']
found = True
break
if not found:
combined.append(d)
return combined
答案 4 :(得分:0)
非最佳,但有效:
>>> from collections import Counter
>>> from pprint import pprint
>>> a = [{'title': 'Learning How to Program', 'views': 1,'url': '/4XvR', 'slug': 'learning-how-to-program'},
... {'title': 'Mastering Programming', 'views': 3,'url': '/7XqR', 'slug': 'mastering-programming'}]
>>> b = [{'title': 'Learning How to Program', 'views': 7,'url': '/4XvR', 'slug': 'learning-how-to-program'},
... {'title': 'Mastering Programming', 'views': 2,'url': '/7XqR', 'slug': 'mastering-programming'},
... {'title': 'Programming Fundamentals', 'views': 1,'url': '/93hB', 'slug': 'programming-fundamentals'}]
>>> summed = sum((Counter({x['slug']: x['views']}) for x in a+b), Counter())
>>> c = dict()
>>> _ = [c.update({x['slug']: x}) for x in a + b]
>>> _ = [c[x].update({'views': summed[x]}) for x in c.keys()]
>>> pprint(c.values())
[{'slug': 'mastering-programming',
'title': 'Mastering Programming',
'url': '/7XqR',
'views': 5},
{'slug': 'programming-fundamentals',
'title': 'Programming Fundamentals',
'url': '/93hB',
'views': 1},
{'slug': 'learning-how-to-program',
'title': 'Learning How to Program',
'url': '/4XvR',
'views': 8}]
基于Martijn的Counter理念,需要更多迭代才能更新 计数器值与其他属性,假设它们不会改变。
请注意,有一些"加密"在发电机中循环......
答案 5 :(得分:0)
一个简单的函数,可以为任何给定数量的列表执行所需的操作:
import itertools
from collections import Counter, OrderedDict
def sum_views(*lists):
views = Counter()
docs = OrderedDict() # to preserve input order
for doc in itertools.chain(*lists):
slug = doc['slug']
views[slug] += doc['views']
docs[slug] = dict(doc) # shallow copy of original dict
docs[slug]['views'] = views[slug]
return docs.values()
答案 6 :(得分:0)
假设您不想将其标题为" title"和"观点"。更专业的方式就是这样写:
def combing(x):
result = {}
for i in x:
h = i.values()
result[h[0]] = result.get(h[0],0)+ h[1]
return result
combing([{'item': 'item1', 'amount': 400}, {'item': 'item2', 'amount':
300}, {'item': 'item1', 'amount': 750}])