I want to create list from dictionary elements - python

I have Nested dictionary something like this.
{'A': {'21-26': 2,
'26-31': 7,
'31-36': 3,
'36-41': 2,
'41-46': 0,
'46-51': 0,
'Above 51': 0},
'B': {'21-26': 2,
'26-31': 11,
'31-36': 5,
'36-41': 4,
'41-46': 1,
'46-51': 0,
'Above 51': 3}}
And I want to create list by key from second dictionary.
And i don't want duplicates in my list.
Required Output is
ls = ['21-26','26-31','31-36','36-41','41-46','46-51','Above 51']
Thank you for your time and consideration.

You can use:
>>> list(set(key for val in d.values() for key in val.keys()))
['21-26', '36-41', '31-36', '46-51', 'Above 51', '26-31', '41-46']
Where d is your dictionary.

Simple set comprehension, then convert to list. a is your dict.
list({k for v in a.values() for k in v.keys()})
Output ordering is random, but you can sort how you like.

Can you use pandas? IF so:
import pandas as pd
a = {'A': {'21-26': 2, '26-31': 7, '31-36': 3, '36-41': 2, '41-46': 0, '46-51': 0, 'Above 51': 0}, 'B': {'21-26': 2, '26-31': 11, '31-36': 5, '36-41': 4, '41-46': 1, '46-51': 0, 'Above 51': 3}}
pd.DataFrame(a).index.to_list()
output:
['21-26', '26-31', '31-36', '36-41', '41-46', '46-51', 'Above 51']

You can use chain.from_iterable() to chain inner dictionaries and dict.fromkeys() to remove duplicates:
from itertools import chain
c = chain.from_iterable(dct.values())
result = list(dict.fromkeys(c))

Related

Add list elements to dict values

I'm learning python and having a hard time with this code. I need to update every dict key value with the elements in the list. The list and dict will always have the same length.
list = [1, 2, 3, 4, 5]
dict = {2433: 0, 2429: 0, 2425: 0, 2423: 0, 2427: 0}
Expected output:
dict = {2433: 1, 2429: 2, 2425: 3, 2423: 4, 2427: 5}
IIUC, you want to create a dictionary from a list of keys (or a dummy dictionary) and a list of values?
lst = [1, 2, 3, 4, 5]
dct = {2433: 0, 2429: 0, 2425: 0, 2423: 0, 2427: 0}
new_dct = dict(zip(dct, lst))
output: {2433: 1, 2429: 2, 2425: 3, 2423: 4, 2427: 5}
NB. do not use list and dict as variable names, those are python builtins

merge two lists into dictionary

I'm trying to merge two lists to dict:
l1 = [1, 3, 6, 0, 1, 1]
l2 = ['foo1', 'foo2', 'foo1', 'foo2', 'foo2', 'bar1']
I'd like to get:
list = [{"foo1": 1},
{"foo2": 3},
{"foo1": 6},
{"foo2": 0},
{"foo2": 1},
{"bar1": 1},]
trying to use zip but get an error :"<zip object at 0x000>"
You can try this:
l1 = [1, 3, 6, 0, 1, 1]
l2 = ['foo1', 'foo2', 'foo1', 'foo2', 'foo2', 'bar1']
data = [{k: v} for k, v in zip(l2, l1)]
print(data)
Output:
[{'foo1': 1}, {'foo2': 3}, {'foo1': 6}, {'foo2': 0}, {'foo2': 1}, {'bar1': 1}]
I wouldn't consider this an ideal data structure though, unless you have a lot more data in the individual dictionaries.
The answer by #Tenacious B achieves what you requested.
You might, however, be better with a dictionary of lists. The keys would be items from l2 and values would be a list containing the corresponding values from l1. A collections.defaultdict makes this easy:
l1 = [1, 3, 6, 0, 1, 1]
l2 = ['foo1', 'foo2', 'foo1', 'foo2', 'foo2', 'bar1']
from collections import defaultdict
d = defaultdict(list)
for k, v in zip(l2, l1):
d[k].append(v)
print(d)
Output:
defaultdict(, {'foo1': [1, 6], 'foo2': [3, 0, 1], 'bar1': [1]})
Now you can access the data by key:
>>> d['foo2']
[3, 0, 1]
>>> d['foo1']
[1, 6]
I'm pretty sure <zip object at 0x0000021A9C9F71C0> is not an error, you just haven't execute the code yet. It is stored in a zip object which is waiting for execution.

How to replicate Pandas merge with inner join only using For and If

I have been trying to replicate Pandas merge join inner using only for's and if's, but I'm having a hard time.
My input will be two lists of dictionaries, and the output should be a list of dictionaries as well.
a = [{'building': 3, 'room':5},{'building': 3, 'room':8},{'building': 2, 'room':3}]
b = [{'building': 3, 'block':4}]
joined_ab = [{'building': 3, 'room':5, 'block':4},{'building': 3, 'room':8, 'block':4}]
Update to original question:
I was looking for something more generic that could go over the dictionaries in the list and test if there's a matching on the other list. If matching then join dictionary, proceed to next dict until list of dict is finished. In short, the code should both work for the original problem, but work as well for the case below:
a = [{'building': 3, 'room':5},{'building': 3, 'room':8},{'building': 2, 'room':3}]
b = [{'building': 3, 'block':4}, {'building': 2, 'block':2}]
returning:
joined_ab:[{'building': 3, 'room':5,'block':4},{'building': 3, 'room':8,'block':4},{'building': 2, 'room':3,'block':2}]
I think I got it, however I am testing several times same dict. Any ideas for jumping to next dict in the list as soon as I find the first match?
nice list comprehension condensed format suggestions? how about using lambda function?
joined_ab = []
for i in b:
for j in a:
for ii in i.items():
for jj in j.items():
if ii == jj:
ab = j.copy()
ab.update(i)
joined_ab.append(ab)
this code returns correct answer:
joined_ab = {'building': 3, 'room': 5, 'block': 4},
{'building': 3, 'room': 8, 'block': 4},
{'building': 2, 'room': 3, 'block': 2}]
If you are using python 3.9, then you can use | option in dictionary to append two dictionaries.
a = [{'building': 3, 'room':5},{'building': 3, 'room':8},{'building': 2, 'room':3}]
b = [{'building': 3, 'block':4}]
joined_ab = [k|b[0] for k in a if k['building']==3]
print (joined_ab)
This will result in:
[{'building': 3, 'room': 5, 'block': 4}, {'building': 3, 'room': 8, 'block': 4}]
If you are using python < 3.9, then you can give:
joined_abx = [{**k,**b[0]} for k in a if k['building']==3]
or
joined_aby = [dict(k,**b[0]) for k in a if k['building']==3]
Output will be same:
[{'building': 3, 'room': 5, 'block': 4}, {'building': 3, 'room': 8, 'block': 4}]

Sum tuples of cartesian product of arbitrary number of dicts

I'd like to do the cartesian product of multiple dicts, based on their keys, and then sum the produced tuples, and return that as a dict. Keys that don't exist in one dict should be ignored (this constraint is ideal, but not necessary; i.e. you may assume all keys exist in all dicts if needed). Below is basically what I'm trying to achieve (example shown with two dicts). Is there a simpler way to do this, and with N dicts?
def doProdSum(inp1, inp2):
prod = defaultdict(lambda: 0)
for key in set(list(inp1.keys())+list(inp2.keys())):
if key not in prod:
prod[key] = []
if key not in inp1 or key not in inp2:
prod[key] = inp1[key] if key in inp1 else inp2[key]
continue
for values in itertools.product(inp1[key], inp2[key]):
prod[key].append(values[0] + values[1])
return prod
x = doProdSum({"a":[0,1,2],"b":[10],"c":[1,2,3,4]}, {"a":[1,1,1],"b":[1,2,3,4,5]})
print(x)
Output (as expected):
{'c': [1, 2, 3, 4], 'b': [11, 12, 13, 14, 15], 'a': [1, 1, 1, 2, 2, 2,
3, 3, 3]}
You can do it like this, by first reorganizing your data by key:
from collections import defaultdict
from itertools import product
def doProdSum(list_of_dicts):
# We reorganize the data by key
lists_by_key = defaultdict(list)
for d in list_of_dicts:
for k, v in d.items():
lists_by_key[k].append(v)
# list_by_key looks like {'a': [[0, 1, 2], [1, 1, 1]], 'b': [[10], [1, 2, 3, 4, 5]],'c': [[1, 2, 3, 4]]}
# Then we generate the output
out = {}
for key, lists in lists_by_key.items():
out[key] = [sum(prod) for prod in product(*lists)]
return out
Example output:
list_of_dicts = [{"a":[0,1,2],"b":[10],"c":[1,2,3,4]}, {"a":[1,1,1],"b":[1,2,3,4,5]}]
doProdSum(list_of_dicts)
# {'a': [1, 1, 1, 2, 2, 2, 3, 3, 3],
# 'b': [11, 12, 13, 14, 15],
# 'c': [1, 2, 3, 4]}

How can I get the values that are common to two dictionaries, even if the keys are different?

Starting from two different dictionaries:
dict_a = {'a': 1, 'b': 3, 'c': 4, 'd': 4, 'e': 6}
dict_b = {'d': 1, 'e': 6, 'a': 3, 'v': 7}
How can I get the common values even if they have different keys? Considering the above dictionaries, I would like to have this output:
common = [1, 3, 6]
Create sets from the values:
list(set(dict_a.values()) & set(dict_b.values()))
This creates an intersection of the unique values in either dictionary:
>>> dict_a = {'a': 1, 'b': 3, 'c': 4, 'd': 4, 'e': 6}
>>> dict_b = {'d': 1, 'e': 6, 'a': 3, 'v': 7}
>>> list(set(dict_a.values()) & set(dict_b.values()))
[1, 3, 6]
Unfortunately, we can't use dictionary views here (which can act like sets), because dictionary values are not required to be unique. Had you asked for just the keys, or the key-value pairs, the set() calls would not have been necessary.
Try this,
commom = [item for item in dict_b.values() if item in dict_a.values()]
The intersection expression & requires 2 sets but the method counterpart can work with any iterable, like dict.values. So here is another version of the Martijn Pieters solution :
list(set(dict_a.values()).intersection(dict_b.values()))
My 2 cents :)

Categories

Resources