Dictionary add values ββfor the same keys
I have a list of dictionaries:
[{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]
I want this to be:
[{'name':'Jay', 'value':'8'},{'name':'roc', 'value':'11'}]
I have tried scrolling, but I cannot find an example where I can do this. Any hints or ideas would be appreciated.
source to share
You can use defaultdict:
lst = [{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]
1) the values ββof the sum for each name:
from collections import defaultdict
result = defaultdict(int)
for d in lst:
result[d['name']] += int(d['value'])
2) converts a name-value pair to a dictionary in a list:
[{'name': name, 'value': value} for name, value in result.items()]
# [{'name': 'roc', 'value': 11}, {'name': 'Jay', 'value': 8}]
Or, if you want the value as type str commented by @Kevin:
[{'name': name, 'value': str(value)} for name, value in result.items()]
β# [{'name': 'roc', 'value': '11'}, {'name': 'Jay', 'value': '8'}]
source to share
This is a good use case itertools.groupby
.
from itertools import groupby
from operator import itemgetter
orig = [{'name':'Jay', 'value':'1'},
{'name':'roc', 'value':'9'},
{'name':'Jay', 'value':'7'},
{'name':'roc', 'value':'2'}]
get_name = itemgetter('name')
result = [{'name': name, 'value': str(sum(int(d['value']) for d in dicts))}
for name, dicts in groupby(sorted(orig, key=get_name), key=get_name)]
Destruction:
-
get_name
is a function that provides a dictionary, returns the value of its "name". Ie,get_name = lambda x: x['name']
. -
sorted
returns a list of dictionaries sorted by key value"name"
. -
groupby
returns an iterator(name, dicts)
, wheredicts
is a list of (ok, generator) dicts sharedname
as key value"name"
. (Grouping occurs only for consecutive items with the same key value, so you need to sort the list in the previous step.) -
The result is a list of new dictionaries using the given name and the sum of all related items
"value"
.
source to share
Similar to Psidom but using collections.Counter
which is an ideal candidate for accumulating integer values.
import collections
d =[{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]
c = collections.Counter()
for sd in d:
c[sd["name"]] += int(sd["value"])
Then you need to rebuild the dicts if necessary by converting back to string.
print([{"name":n,"value":str(v)} for n,v in c.items()])
result:
[{'name': 'Jay', 'value': '8'}, {'name': 'roc', 'value': '11'}]
source to share
For completeness, without collections.defaultdict
:
data = [{'name': 'Jay', 'value': '1'}, {'name': 'roc', 'value': '9'},
{'name': 'Jay', 'value': '7'}, {'name': 'roc', 'value': '2'}]
result = {}
# concetrate
for element in data:
result[element["name"]] = result.get(element["name"], 0) + int(element["value"])
# unpack
result = [{"name": element, "value": result[element]} for element in result]
# optionally, you can loop through result.items()
# you can, also, turn back result[elements] to str if needed
print(result)
# prints: [{'name': 'Jay', 'value': 8}, {'name': 'roc', 'value': 11}]
source to share
Another way to solve your question is with the groupby
from module itertools
:
from itertools import groupby
a = [{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]
final = []
for k,v in groupby(sorted(a, key= lambda x: x["name"]), lambda x: x["name"]):
final.append({"name": k, "value": str(sum(int(j["value"]) for j in list(v)))})
print(final)
Output:
[{'name': 'Jay', 'value': '8'}, {'name': 'roc', 'value': '11'}]
source to share
Here's another way to use pandas
names = [{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},
{'name':'roc', 'value':'2'}]
df = pd.DataFrame(names)
df['value'] = df['value'].astype(int)
group = df.groupby('name')['value'].sum().to_dict()
result = [{'name': name, 'value': value} for name, value in group.items()]
What are the outputs:
[{'value': 8, 'name': 'Jay'}, {'value': 11, 'name': 'roc'}]
source to share
ld = [{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]
tempDict = {}
finalList = []
for d in ld:
name = d['name']
value = d['value']
if name not in tempDict:
tempDict[name] = 0
tempDict[name] += int(value)
#tempDict => {'Jay': 8, 'roc': 11}
for name,value in tempDict.items():
finalList.append({'name':name,'value':value})
print(finalList)
# [{'name': 'Jay', 'value': 8}, {'name': 'roc', 'value': 11}]
source to share