Merge multiple key in dictionary with same values inside an array - python

I need to merge three dictionaries with array values into a single dict based on if they have same values inside the array. The dictionaries is like this:
data = {
'A1':['Cheese','Cupcake', 'Salad','Sandwich'],
'A2':['Cheese','Cupcake', 'Pasta','Pudding'],
'A3':['Pudding','Pasta', 'Salad','Sandwich']
}
Then, the output would be like this:
{
'A1,A2':['Cheese','Cupcake']
'A1,A3':['Salad', 'Sandwich']
'A2,A3':['Pudding','Pasta']
}
I've tried this:
tmp = {}
for key, value in data.items():
if value in tmp:
tmp[value].append(key)
else:
tmp[value] = [ key ]
print(tmp)
But it only works if the values isn't a list or array. Any solution?

Given you use case, you could use itertools.combinations and set intersection:
data = {
'A1':['Cheese','Cupcake', 'Salad','Sandwich'],
'A2':['Cheese','Cupcake', 'Pasta','Pudding'],
'A3':['Pudding','Pasta', 'Salad','Sandwich']
}
from itertools import combinations
out = {f'{a},{b}': list(set(data[a]).intersection(data[b]))
for a,b in combinations(data, 2)}
output:
{'A1,A2': ['Cupcake', 'Cheese'],
'A1,A3': ['Sandwich', 'Salad'],
'A2,A3': ['Pasta', 'Pudding']}

Related

Create a list of dictionaries with values from another list in Python

I have a list of values that looks like this : values = [2.5,3.6,7.5,6.4],
Is it possible to create several dictionaries with the values from this list and the same key value for all items, so the final output will look like this:
list_of_dic = [{'interest rate':2.5}, {'interest rate'}:3.6, {'interest rate':7.5}, {'interest rate':6.4}]
You can achieve this by using list comprehension:
return [{'interest rate': val} for val in values]
or
a = []
for val in values:
a.append({
'interest rate':val
})
return a
Both do the same thing
Sure, just make a second table "labels" with your labels.
Then :
def f(labels, values):
l = [] # here is the result list you want to fill with dicts
foreach i in range(0, len(values)): # for each value
d = dict{} # create dict
d[values[i]] = labels[i] # put your key and value in it
l.append(d) # add it to your result list
return l # return the result list

get maximum valued dictionary from list of dictionaries in python

I have this list.
dict_list = [{"rp":1,"vi":100},{"rp":2,"vi":70},{"rp":1,"vi":200},{"rp":1,"vi":150},{"rp":2,"vi":300},{"rp":3, "vi":120 }]
I want output as:
[ {"rp":1,"vi":200},{"rp":2,"vi":300},{"rp":3,"vi":120}]
Can anyone help??
You can build a temporary dictionary using the 'rp' values as keys and feeding the data in order of 'vi' value to retain the highest 'vi' value for each unique 'rp' key. Then convert the values of that temporary dictionary into a list of dictionaries:
R = [*{d["rp"]:d for d in sorted(dict_list,key=lambda d:d["vi"])}.values()]
print(R)
[{'rp': 2, 'vi': 300}, {'rp': 1, 'vi': 200}, {'rp': 3, 'vi': 120}]
One solution could be to create a dictionary with key as the rp value and value as the maximum vi value.
Use the created dictionary to create the required list
dict_list = [{"rp":1,"vi":100},{"rp":2,"vi":70},{"rp":1,"vi":200},{"rp":1,"vi":150},{"rp":2,"vi":300},{"rp":3, "vi":120 }]
res = dict()
for elt in dict_list:
res[elt["rp"]] = max(res.get(elt["rp"], 0), elt["vi"]) # overwrite with max for matching keys
dict_list = [{"rp": key, "vi": value} for key, value in res.items()]
print(dict_list)
I am not sure if this is the most elegant way to do it but I hope it helps.
you can try to use pandas for something like this:
import pandas as pd
dict_list = [{"rp":1,"vi":100},{"rp":2,"vi":70},{"rp":1,"vi":200},
{"rp":1,"vi":150},{"rp":2,"vi":300},{"rp":3, "vi":120 }]
full = pd.DataFrame(dict_list)
rp_list = pd.Series(full['rp']).unique()
new= []
for rp in rp_list:
values = full.loc[full['rp'] == rp]
max_value = values["vi"].max()
new.append({'rp':rp,'vi':max_value})
print (new)

Python dictionary with key value pair as value for a key

I want to know how to create a dictionary with key value pair and value should have another values.
For example:
{key:{value1 : [a,b,c] , value2 : [d,e,f] , value3 : [g,h,i] } }
I tried,
a = {}
a.setdefault(key,{})[value] = a
a.setdefault(key,{})[value] = b
a.setdefault(key,{})[value] = c
then a returns
{ key: {value : c } }
For value last one added is only getting.
from collections import defaultdict
#create nested dict using defaultdict
a = defaultdict(lambda:defaultdict(list))
#above line will create dict of dict where internal dict holds list of values
a['key']['value'].append('a')
a['key']['value'].append('b')
a['key']['value'].append('c')
a looks like {'key':{'value':[a,b,c]}}
#To read data iterate over nested dict
for k,v in a.iteritems():
print k
print v['value']

Efficiently filtering nested list of dictionary

I have a nested list of dictionary like follows:
list_of_dict = [
{
"key": "key1",
"data": [
{
"u_key": "u_key_1",
"value": "value_1"
},
{
"u_key": "u_key_2",
"value": "value_2"
}
]
},
{
"key": "key2",
"data": [
{
"u_key": "u_key_1",
"value": "value_3"
},
{
"u_key": "u_key_2",
"value": "value_4"
}
]
}
]
As you can see list_of_dict is a list of dict and inside that, data is also a list of dict. Assume that all the objects inside list_of_dict and data has similar structure and all the keys are always present.
In the next step I convert list_of_dict to list_of_tuples, where first element of tuple is key followed by all the values against value key inside data
list_of_tuples = [
('key1', 'value_1'),
('key1', 'value_2'),
('key2', 'value_3'),
('key2','value_4')
]
The final step is comparison with a list(comparison_list). List contains string values. The values inside the list CAN be from the value key inside data. I need to check if any value inside comparison_list is inside list_of_tuples and fetch the key(first item of tuple) of that value.
comparison_list = ['value_1', 'value_2']
My expected output is:
out = ['key1', 'key1']
My solution is follows:
>>> list_of_tuples = [(c.get('key'),x.get('value'))
for c in list_of_dict for x in c.get('data')]
>>> for t in list_of_tuple:
if t[1] in comparison_list:
print("Found: {}".format(t[0]))
So summary of problem is that I have list of values(comparison_list) which I need to find inside data array.
The dataset that I am operating on is quite huge(>100M). I am looking to speed up my solution and also make it more compact and readable.
Can I somehow skip the step where I create list_of_tuples and do the comparison directly?
There are a few simple optimization you can try:
make comparison_list a set so the lookup is O(1) instead of O(n)
make list_of_tuples a generator, so you don't have to materialize all the entries at once
you can also integrate the condition into the generator itself
Example:
comparison_set = set(['value_1', 'value_2'])
tuples_generator = ((c['key'], x['value'])
for c in list_of_dict for x in c['data']
if x['value'] in comparison_set)
print(*tuples_generator)
# ('key1', 'value_1') ('key1', 'value_2')
Of course, you can also keep the comparison separate from the generator:
tuples_generator = ((c['key'], x['value'])
for c in list_of_dict for x in c['data'])
for k, v in tuples_generator:
if v in comparison_set:
print(k, v)
Or you could instead create a dict mapping values from comparison_set to keys from list_of_dicts. This will make finding the key to a particular value faster, but note that you can then only keep one key to each value.
values_dict = {x['value']: c['key']
for c in list_of_dict for x in c['data']
if x['value'] in comparison_set}
print(values_dict)
# {'value_2': 'key1', 'value_1': 'key1'}
In last step you can use filter something like this instead of iterating over that:
comparison_list = ['value_1', 'value_2']
print(list(filter(lambda x:x[1] in comparison_list,list_of_tuples)))
output:
[('key1', 'value_1'), ('key1', 'value_2')]

How do I find an item in an array of dictionaries?

Suppose I have this:
list = [ { 'p1':'v1' } ,{ 'p2':'v2' } ,{ 'p3':'v3' } ]
I need to find p2 and get its value.
You can try the following ... That will return all the values equivilant to the givenKey in all dictionaries.
ans = [d[key] for d in list if d.has_key(key)]
If this is what your actual code looks like (each key is unique), you should just use one dictionary:
things = { 'p1':'v1', 'p2':'v2', 'p3':'v3' }
do_something(things['p2'])
You can convert a list of dictionaries to one dictionary by merging them with update (but this will overwrite duplicate keys):
dict = {}
for item in list:
dict.update(item)
do_something(dict['p2'])
If that's not possible, you'll need to just loop through them:
for item in list:
if 'p2' in item:
do_something(item['p2'])
If you expect multiple results, you can also build up a list:
p2s = []
for item in list:
if 'p2' in item:
p2s.append(item['p2'])
Also, I wouldn't recommend actually naming any variables dict or list, since that will cause problems with the built-in dict() and list() functions.
These shouldn't be stored in a list to begin with, they should be stored in a dictionary. Since they're stored in a list, though, you can either search them as they are:
lst = [ { 'p1':'v1' } ,{ 'p2':'v2' } ,{ 'p3':'v3' } ]
p2 = next(d["p2"] for d in lst if "p2" in d)
Or turn them into a dictionary:
dct = {}
any(dct.update(d) for d in lst)
p2 = dct["p2"]
You can also use this one-liner:
filter(lambda x: 'p2' in x, list)[0]['p2']
if you have more than one 'p2', this will pick out the first; if you have none, it will raise IndexError.
for d in list:
if d.has_key("p2"):
return d['p2']
If it's a oneoff lookup, you can do something like this
>>> [i['p2'] for i in my_list if 'p2' in i]
['v2']
If you need to look up multiple keys, you should consider converting the list to something that can do key lookups in constant time (such as a dict)
>>> my_list = [ { 'p1':'v1' } ,{ 'p2':'v2' } ,{ 'p3':'v3' } ]
>>> my_dict = dict(i.popitem() for i in my_list)
>>> my_dict['p2']
'v2'
Start by flattening the list of dictionaries out to a dictionary, then you can index it by key and get the value:
{k:v for x in list for k,v in x.iteritems()}['p2']

Categories