Summation on an element inside nested dicts in a list - python

I have a list of nested dictionaries
timedata = [
{'time': 1, 'distance': {'a': 300, 'b': 3}},
{'time': 2, 'distance': {'a': 600, 'b': 1}},
{'time': 3, 'distance': {'a': 600, 'b': 4}},
{'time': 4, 'distance': {'a': 300, 'b': 3}},
]
Any ideas how to calculate the summation of 'a' from all dicts inside the list?

To go inside timedata, use [], similarly for nestings inside it. To sum conttents, use sum():
print(sum([di['distance']['a'] for di in timedata]))

try this;
sum = 0
for i in timedata:
sum += i['distance']['a']
print(sum)

Related

how to count duplicate of dictionarys inside the list?

Was wondering if anyone could help me with counting duplicate dictionarys. I have this list:
a = [{'key1':1, 'key2':2, 'key3':3, 'count': 0},
{'key1':1, 'key2':2, 'key3':4, 'count': 0},
{'key1':3, 'key2':2, 'key3':4, 'count': 0},
{'key1':1, 'key2':2, 'key3':3, 'count': 0}]
i`m lookig to count all duplicates and once it is match remove copy and append to that dictionry ['count'] += 1. so final result might look like
a = [{'key1':1, 'key2':2, 'key3':3, 'count': 2},
{'key1':1, 'key2':2, 'key3':4, 'count': 0},
{'key1':3, 'key2':2, 'key3':4, 'count': 0}]
i did tryed simple aprouch such as which didnt worked:
a = [{'key1':1, 'key2':2, 'key3':3, 'count': 0},
{'key1':1, 'key2':2, 'key3':4, 'count': 0},
{'key1':3, 'key2':2, 'key3':4, 'count': 0},
{'key1':1, 'key2':2, 'key3':3, 'count': 0}]
for i in range(len(a)):
for n in range(len(a)):
if a[i]['key1'] == a[n]['key1'] and a[i]['key2'] == a[n]['key2'] and a[i]['key3'] == a[n]['key3']:
a[i]['count'] += 1
del a[n]
was thinking aswell there should be some simpler aprouch. thanks
You can leverage Counter method in the collections module.
import collections
count = collections.Counter([tuple(d.items()) for d in a])
[dict(k) | {c:v} for (*k, (c,_)), v in count.items()]
this looks like:
[{'key1': 1, 'key2': 2, 'key3': 3, 'count': 2},
{'key1': 1, 'key2': 2, 'key3': 4, 'count': 1},
{'key1': 3, 'key2': 2, 'key3': 4, 'count': 1}]

Strange behaviou of dict python [duplicate]

This question already has answers here:
Python dict.fromkeys return same id element
(2 answers)
Closed 3 years ago.
I've a dict code snippets which is not behaving as expected
a = {"d1":{"a":1,"b":2,"c":4},"d2":{"a":1,"b":2,"c":4},"d3":{"a":1,"b":2,"c":4}}
b = {"d1":{"a":1,"b":0},"d2":{"a":0,"c":4},"d3":{"a":1,"b":2,"c":4}}
c = dict.fromkeys(a.keys(),{})
print(c)
for doc in b.keys():
for word in b[doc].keys():
c[doc][word] = a[doc][word]*b[doc][word]
print(c)
output is:
{'d1': {}, 'd2': {}, 'd3': {}}
{'d1': {'a': 1, 'b': 4, 'c': 16}, 'd2': {'a': 1, 'b': 4, 'c': 16}, 'd3': {'a': 1, 'b': 4, 'c': 16}}
instead of:
{'d1': {}, 'd2': {}, 'd3': {}}
{'d1': {'a': 1, 'b': 0}, 'd2': {'a': 0, 'c': 16}, 'd3': {'a': 1, 'b': 4, 'c': 16}}
I very confused now any insights would be helpful.
The problem is because you are using a mutable object as the second argument for fromkeys.
This is much clearer here:
d = dict.fromkeys(['a', 'b'], [])
d['a'].append(1)
print(d)
Outputs
{'a': [1], 'b': [1]}
Made a modification to your for loop :
for doc in b.keys():
for word in b[doc].keys():
if doc not in c:
c[doc]={}
c[doc][word] = a[doc][word]*b[doc][word]
print(c)
#{'d1': {'a': 1, 'b': 0}, 'd2': {'a': 0, 'c': 16}, 'd3': {'a': 1, 'b': 4, 'c': 16}}
Use a dictionary comprehension to create c instead:
c = {k: {} for k in a.keys()}
for doc in b.keys():
for word in b[doc].keys():
c[doc][word] = a[doc][word]*b[doc][word]
print(c)
# {'d1': {'a': 1, 'b': 0}, 'd2': {'a': 0, 'c': 16}, 'd3': {'a': 1, 'b': 4, 'c': 16}}
Notice the difference when you use fromkeys vs dictionary comprehension:
c = dict.fromkeys(a.keys(),{})
print([id(o) for o in c.values()])
# [53649152, 53649152, 53649152]
# same object reference id!
c = {k: {} for k in a.keys()}
print([id(o) for o in c.values()])
# [53710208, 53649104, 14445232]
# each object has different reference id

Getting the key of the element with the highest value? The value is another dictionary

I am trying to find the key of element which has the highest value. The values are another dictionary, so the method mentioned over here: Getting key with maximum value in dictionary? cannot be used.
The structure is like this:
{'a': {'points': 7, 'difference': 0}, 'b': {'points': 6, 'difference': 1}, 'c': {'points': 4, 'difference': -3}, 'd': {'points': 7, 'difference': 2}}
The element which has the most number of points should be the max element, and if points are same then the element with the larger difference should be chosen.
So the max element in this case is d.
I know I can I use for loop and find the maximum element, but is there any other way to do it?
d = {'a': {'points': 7, 'difference': 0}, 'b': {'points': 6, 'difference': 1}, 'c': {'points': 4, 'difference': -3}, 'd': {'points': 7, 'difference': 2}}
result = max(d.keys(), key = lambda k: (a[k]["points"], a[k]["difference"]))
result will give you the maximum key based on that key's points (or that key's differences if the points are a tie)
You can do something like this:
my_dict = {'a': {'points': 7, 'difference': 0}, 'b': {'points': 6, 'difference': 1}, 'c': {'points': 4, 'difference': -3}, 'd': {'points': 7, 'difference': 2}}
_key, _value = '', {'points': 0, 'difference': 0}
for key, elm in my_dict.items():
if elm['points'] >= _value['points']:
if elm['difference'] >= _value['difference']:
_key, _value = key, elm
out = {_key: _value}
print(out)
Output:
{'d': {'points': 7, 'difference': 2}}
Or, using max:
out = max(my_dict.items(), key=lambda k: (k[1]['points'], k[1]['difference']))
out:
('d', {'points': 7, 'difference': 2})

Find and count equal dicts inside a list

I have a list with multiple dicts in, I need to check which dicts are repeated and create a new list with only a single occurrence of each but with the amount of repeated elements in the first list.
For example:
I have that list:
[{'a': 123, 'b': 1234, 'c': 'john', 'amount': 1},
{'a': 456, 'b': 1234, 'c': 'doe','amount': 1},
{'a': 456, 'b': 1234, 'c': 'steve','amount': 1},
{'a': 123, 'b': 1234, 'c': 'john','amount': 1},
{'a': 123, 'b': 1234, 'c': 'john','amount': 1}]
I need to output:
[{'a': 123, 'b': 1234, 'c': 'john', 'amount': 3},
{'a': 456, 'b': 1234, 'c': 'steve','amount': 1},
{'a': 456, 'b': 1234, 'c': 'doe','amount': 1}]
I've tried some things I found by Googling but nothing works completely, the last that I've tried let me know where the repeated ones where, but I'm stuck in what to do next.
def index(lst, element):
result = []
offset = -1
while True:
try:
offset = lst.index(element, offset+1)
except ValueError:
return result
result.append(offset)
for i in l:
if len(index(l,i)) > 1:
i['amount'] += 1
print l
But it returns
[{'a': 123, 'c': 'john', 'b': 1234, 'amount': 2},
{'a': 456, 'c': 'doe', 'b': 1234, 'amount': 1},
{'a': 456, 'c': 'steve', 'b': 1234, 'amount': 1},
{'a': 123, 'c': 'john', 'b': 1234, 'amount': 2},
{'a': 123, 'c': 'john', 'b': 1234, 'amount': 1}]
Here is an option using pandas by which we can concatenate the dictionary into a data frame, and then we can groupby column a, b and c and calculate the sum of amount. And if we want a dictionary back, pandas data frame has a built in to_dict() function. Specifying the parameter as index, we can get a dictionary as the desired output:
import pandas as pd
list(pd.DataFrame(mylist).groupby(['a', 'b', 'c']).sum().reset_index().to_dict('index').values())
# [{'a': 123, 'amount': 3, 'b': 1234, 'c': 'john'},
# {'a': 456, 'amount': 1, 'b': 1234, 'c': 'doe'},
# {'a': 456, 'amount': 1, 'b': 1234, 'c': 'steve'}]

Pythonic sort a list of dictionaries in a tricky order

I have a list of id's sorted in a proper oder:
ids = [1, 2, 4, 6, 5, 0, 3]
I also have a list of dictionaries, sorted in some random way:
rez = [{'val': 7, 'id': 1}, {'val': 8, 'id': 2}, {'val': 2, 'id': 3}, {'val': 0, 'id': 4}, {'val': -1, 'id': 5}, {'val': -4, 'id': 6}, {'val': 9, 'id': 0}]
My intention is to sort rez list in a way that corresponds to ids:
rez = [{'val': 7, 'id': 1}, {'val': 8, 'id': 2}, {'val': 0, 'id': 4}, {'val': -4, 'id': 6}, {'val': -1, 'id': 5}, {'val': 9, 'id': 0}, {'val': 2, 'id': 3}]
I tried:
rez.sort(key = lambda x: ids.index(x['id']))
However that way is too slow for me, as len(ids) > 150K, and each dict actually had a lot of keys (some values there are strings). Any suggestion how to do it in the most pythonic, but still fastest way?
You don't need to sort because ids specifies the entire ordering of the result. You just need to pick the correct elements by their ids:
rez_dict = {d['id']:d for d in rez}
rez_ordered = [rez_dict[id] for id in ids]
Which gives:
>>> rez_ordered
[{'id': 1, 'val': 7}, {'id': 2, 'val': 8}, {'id': 4, 'val': 0}, {'id': 6, 'val': -4}, {'id': 5, 'val': -1}, {'id': 0, 'val': 9}, {'id': 3, 'val': 2}]
This should be faster than sorting because it can be done in linear time on average, while sort is O(nlogn).
Note that this assumes that there will be one entry per id, as in your example.
I think you are on the right track. If you need to speed it up, because your list is too long and you are having quadratic complexity, you can turn the list into a dictionary first, mapping the ids to their respective indices.
indices = {id_: pos for pos, id_ in enumerate(ids)}
rez.sort(key = lambda x: indices[x['id']])
This way, indices is {0: 5, 1: 0, 2: 1, 3: 6, 4: 2, 5: 4, 6: 3}, and rez is
[{'id': 1, 'val': 7},
{'id': 2, 'val': 8},
{'id': 4, 'val': 0},
{'id': 6, 'val': -4},
{'id': 5, 'val': -1},
{'id': 0, 'val': 9},
{'id': 3, 'val': 2}]

Categories

Resources