Merging two dictionaries of different sizes and different values - python

If I have two different dictionaries I have created from Queries of different sizes
dictionary1:
{'id': 1 , 'passCount': 3}, {'id': 2 , 'passCount': 4}, {'id': 5 , 'passCount': 7}, {'id': 6, 'passCount': 3}
dictionary2:
{'id': 1 , 'failCount': 1}, {'id': 3 , 'failCount': 2}, {'id': 5 , 'failCount': 3}
Originally, I created a master list from these two dictionaries:
List = []
for i in dictionary1:
for j in dictionary2:
if i['id'] = j['id]:
List.append[i['id'],i['passCount'],j['failCount']]
else:
List.append[i['id'],i['passCount'],0]
List.append[j['id'],0, j['failCount']
return List
When I would print this List out for my data, I would only get a List of id's that match, and would not take into account the other ones.
For that reason I want to print a dictionary where I could get it to print
{'id' = 1, 'passCount' = 3, 'failCount' = 1}, {'id': 2 , 'passCount': 4, 'failCount' = 0}... and so on without deleting any of the id's
Thanks

Short solution using dict.setdefault and dict.update methods:
l1 = [{'id': 1 , 'passCount': 3}, {'id': 2 , 'passCount': 4}, {'id': 5 , 'passCount': 7}, {'id': 6, 'passCount': 3}]
l2 = [{'id': 1 , 'failCount': 1}, {'id': 3 , 'failCount': 2}, {'id': 5 , 'failCount': 3}]
grouped = {}
for d in l1+l2:
grouped.setdefault(d['id'], {'failCount':0, 'passCount': 0}).update(d)
result = [d for d in grouped.values()]
print(result)
The output:
[{'passCount': 3, 'id': 1, 'failCount': 1}, {'passCount': 4, 'id': 2, 'failCount': 0}, {'passCount': 0, 'id': 3, 'failCount': 2}, {'passCount': 7, 'id': 5, 'failCount': 3}, {'passCount': 3, 'id': 6, 'failCount': 0}]

Maybe they're two different lists ,not dictionaries,so I assume they're two lists:
failCount set to 0 by default,you can try this:
a=[{'id': 1 , 'passCount': 3}, {'id': 2 , 'passCount': 4}, {'id': 5 , 'passCount': 7}, {'id': 6, 'passCount': 3}]
b=[{'id': 1 , 'failCount': 1}, {'id': 3 , 'failCount': 2}, {'id': 5 , 'failCount': 3}]
for j in a:
j.update({'failCount': 0})
for i in b:
if i["id"]==j["id"]:
j.update(i)
print(a)
Output:
[{'id': 1, 'passCount': 3, 'failCount': 1}, {'id': 2, 'passCount': 4, 'failCount': 0}, {'id': 5, 'passCount': 7, 'failCount': 3}, {'id': 6, 'passCount': 3, 'failCount': 0}]

Related

Create tuple from key-value

I have a list with dictionary inside, with the following keys: id, external_id_client, product_id, as below:
[{'id': 3, 'external_id_client': '7298', 'product_id': 13},
{'id': 3, 'external_id_client': '7298', 'product_id': 8},
{'id': 4, 'external_id_client': '3', 'product_id': 12},
{'id': 4, 'external_id_client': '3', 'product_id': 9},
{'id': 5, 'external_id_client': '4', 'product_id': 12}]
I need that if the ID and external_id are repeated and I have information in the product_id key it creates a tuple in the product_id.
Expected output:
[{'id': 3, 'external_id_client': '7298', 'product_id': (13, 8)},
{'id': 4, 'external_id_client': '3', 'product_id': (12, 9)},
{'id': 5, 'external_id_client': '4', 'product_id': (12)}]
How can I do this?
You can use itertools.groupby for this:
from itertools import groupby
lst = [
{'id': 3, 'external_id_client': '7298', 'product_id': 13},
{'id': 3, 'external_id_client': '7298', 'product_id': 8},
{'id': 4, 'external_id_client': '3', 'product_id': 12},
{'id': 4, 'external_id_client': '3', 'product_id': 9},
{'id': 5, 'external_id_client': '4', 'product_id': 12}
]
result = [
{
"id": itemid,
"external_id_client": client,
"product_id": tuple(item["product_id"] for item in group)
}
for (itemid, client), group
in groupby(lst, key = lambda item: (item["id"], item["external_id_client"]))
]

Sort list of dicts by specific list of values

I'm trying to code a faster way to solve the following problem but I don't know how to do it:
I have the following list of dicts and list of identifiers:
list_of_dicts = [{'id': 1, 'name': 'A'}, {'id': 2, 'name': 'B'}, {'id': 3, 'name': 'C'}, {'id': 4, 'name': 'D'}]
list_of_ids = [1, 3, 2, 4, 1, 3, 4]
I'd like to have the following output:
[{'id': 1, 'name': 'A'}, {'id': 3, 'name': 'C'}, {'id': 2, 'name': 'B'}, {'id': 4, 'name': 'D'}, {'id': 1, 'name': 'A'}, {'id': 3, 'name': 'C'}, {'id': 4, 'name': 'D'}]
The way I'm doing it is:
list_of_dict_ids = [d['id'] for d in list_of_dicts]
ordered_list_by_ids = [list_of_dicts[list_of_dict_ids.index(i)] for i in list_of_ids]
Is there any faster way to do it?
You can do like this :
dic = {d["id"]: d for d in list_of_dicts}
dic
>>>{1: {'id': 1}, 2: {'id': 2}, 3: {'id': 3}, 4: {'id': 4}}
lst =[dic[i] for i in list_of_ids]
lst
>>>[{'id': 1}, {'id': 3}, {'id': 2}, {'id': 4}, {'id': 1}, {'id': 3}, {'id': 4}]

Couldn't rename field in python list (key, value structure)

I have below list with nested lists (sort of key,values)
inp1=[{'id': 0, 'name': 98, 'value': 9}, {'id': 1, 'name': 66, 'value': 8}, {'id': 2, 'name': 29, 'value': 5}, {'id': 3, 'name': 99, 'value': 3}, {'id': 4, 'name': 15, 'value': 9}]
Am trying to replace 'name' with 'wid' and 'value' with 'wrt', how can I do it on same list?
My output should be like
inp1=[{'id': 0, 'wid': 98, 'wrt': 9}, {'id': 1, 'wid': 66, 'wrt': 8}, {'id': 2, 'wid': 29, 'wrt': 5}, {'id': 3, 'wid': 99, 'wrt': 3}, {'id': 4, 'wid': 15, 'wrt': 9}]
I tried below, but it doesn't work as list cannot be indexed with string but integer
inp1['name'] = inp1['wid']
inp1['value'] = inp1['wrt']
I tried if I can find any examples, but mostly I found only this for dictionary and not list.
You need to iterate each item, and remove the old entry (dict.pop is handy for this - it removes an entry and return the value) and assign to new keyes:
>>> inp1 = [
... {'id': 0, 'name': 98, 'value': 9},
... {'id': 1, 'name': 66, 'value': 8},
... {'id': 2, 'name': 29, 'value': 5},
... {'id': 3, 'name': 99, 'value': 3},
... {'id': 4, 'name': 15, 'value': 9}
... ]
>>>
>>> for d in inp1:
... d['wid'] = d.pop('name')
... d['wrt'] = d.pop('value')
...
>>> inp1
[{'wid': 98, 'id': 0, 'wrt': 9},
{'wid': 66, 'id': 1, 'wrt': 8},
{'wid': 29, 'id': 2, 'wrt': 5},
{'wid': 99, 'id': 3, 'wrt': 3},
{'wid': 15, 'id': 4, 'wrt': 9}]
def f(item):
if(item.has_key('name') and not item.has_key('wid')):
item['wid']=item.pop('name')
if(item.has_key('value') and not item.has_key('wrt')):
item['wrt']=item.pop('value')
map(f,inp1)
Output:
[{'wrt': 9, 'wid': 98, 'id': 0}, {'wrt': 8, 'wid': 66, 'id': 1}, {'wrt': 5, 'wid': 29, 'id': 2}, {'wrt': 3, 'wid': 99, 'id': 3}, {'wrt': 9, 'wid': 15, 'id': 4}]

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}]

python: iterate through list and replace elements with corresponding dictionary values

I am trying to replace list element value with value looked up in dictionary how do I do that?
list = [1, 3, 2, 10]
d = {'id': 1, 'val': 30},{'id': 2, 'val': 53}, {'id': 3, 'val': 1}, {'id': 4, 'val': 9}, {'id': 5, 'val': 2}, {'id': 6, 'val': 6}, {'id': 7, 'val': 11}, {'id': 8, 'val': 89}, {'id': 9, 'val': 2}, {'id': 10, 'val': 4}
for i in list:
for key, v in d.iteritems():
???
???
so at the end I am expecting:
list = [30, 1, 53, 4]
thank you
D2 = dict((x['id'], x['val']) for x in D)
L2 = [D2[x] for x in L]
td = (
{'val': 30, 'id': 1},
{'val': 53, 'id': 2},
{'val': 1, 'id': 3},
{'val': 9, 'id': 4},
{'val': 2, 'id': 5},
{'val': 6, 'id': 6},
{'val': 11, 'id': 7},
{'val': 89, 'id': 8},
{'val': 2, 'id': 9},
{'val': 4, 'id': 10}
)
source_list = [1, 3, 2, 10]
final_list = []
for item in source_list:
for d in td:
if d['id'] == item:
final_list.append(d['val'])
print('Source : ', source_list)
print('Final : ', final_list)
Result
Source : [1, 3, 2, 10]
Final : [30, 1, 53, 4]

Categories

Resources