Separating dictionary into smaller dictionaries - python

I have a dictionary and want to divide it into smaller dictionaries, for example for:
dic = {1:(2,6), 3:(4,5)}
I want to loop it and have a "current" dictionary current = {1:2, 3:4} for first iteration, and current {1:6, 3:5} for the second iteration. Here's what I've tried (and doesn't work):
dic = {1:(2,6), 3:(4,5)}
for i in range (0,1):
for key in dic:
current = {}
current[key] = dic[key][i]
print (current)
this outputs {3:4} and {3:5}, it skips the key "1" for some reason. How do i fix this?
Also, how do I find the number of the values of the keys assuming every key has equal number of values? e.g. for {2:[3,4,5,7], 3:[1,0,3,1]} that would be 4.

You are overwriting current on each iteration, define it before iterating, and range(0, 1) loops through [0] only:
dic = {1:(2,6), 3:(4,5)}
for i in range(2):
current = {}
for key in dic:
current[key] = dic[key][i]
print(current)

Alternatively, you could create the new dictionaries, iterate through the keys of the original dict and create the dictionaries accordingly:
dic = {1:(2,6), 3:(4,5)}
d1, d2 = {}, {}
for key, v in dic.items():
d1[key], d2[key] = v
print(d1, d2)
Which prints out:
{1: 2, 3: 4} {1: 6, 3: 5}
d1[key], d2[key] = v simply unpacks the value for v in d1[key] and d2[key] accordingly.

Related

inversing a dictionary in python with duplicate values

I need to inverse a dictionary so that each old value will now be a key and the old keys will be the new values.
The trick is that there could be multiple values that are the same in the old dictionary so I need each value in the new dictionary to be a list, and if there were identical values in the old dictionary then they both will be in the list of the value of the new dictionary.
for example:
the dictionary {"python" : 1, "is" : 1, "cool" : 2}
would end up as: {1 : ["python", "is"], 2 : ["cool"]}
this is what I tried:
def inverse_dict(my_dict):
new_dict = {}
values_list = list(my_dict.values())
new_dict = new_dict.fromkeys(values_list)
for key in new_dict:
new_dict[key] = []
for old_key in my_dict:
new_dict[my_dict[old_key]] = list(new_dict[my_dict[old_key]]).append(old_key)
return new_dict
Would greatly appreciate any help with my approach (and better approaches to the problem) as I am very new to Python, thanks!
You can use dict.setdefault check if a key exists in the dictionary and if not, create new value (in this case empty list []):
d = {"python" : 1, "is" : 1, "cool" : 2}
reversed_d = {}
for k, v in d.items():
reversed_d.setdefault(v, []).append(k)
print(reversed_d)
Prints:
{1: ['python', 'is'], 2: ['cool']}
This can be more explicitly rewritten as:
d = {"python" : 1, "is" : 1, "cool" : 2}
reversed_d = {}
for k, v in d.items():
if v not in reversed_d:
reversed_d[v] = [k]
else:
reversed_d[v].append(k)
print(reversed_d)
You can use a defaultdict to avoid the pre-fill step
from collections import defaultdict
def inverse_dict(my_dict: dict):
new_dict = defaultdict(list)
for k, v in my_dict.items():
new_dict[v].append(k)
return new_dict
Though I prefer #azro's answer with the default dict, another solution is doing it with dictionary and list comprehensions.
It looks like this:
{value : [key for key in my_dict if my_dict[key] == value] for value in set(my_dict.values())}
What it does is runs over the values of the dictionary without duplicates - set(my_dict.values()).
It builds every value as a key (because it's on the left side of the ":").
And its value is a list of the keys that point to that value - [key for key in my_dict if my_dict[key] == value].

Merging two columns of a dataframe which contains dictionaries and storing it into other column in a data frame

I have a data frame df which has two columns a and b which contains dictionaries and I want to merge these two dictionaries and store the merged dictionaries in a new columns c. One sample data point is :
df :
a b c
------------------------------------------------------------
{x:{y:{z:u}} {w:{f:{h:l}} {x:{y:{z:u}},{w:{f:{h:l}}
I have a and b and I want c.
I have a function that merges the two dictionaries but I am not able to assign the merge dictionaries to column c.
The function that I have for merging two dictionaries:
# Function for merging two dictionaries and adding values if keys are same
def merge_and_add(dict1, dict2):
# We loop over the key and value pairs of the second dictionary...
for k, v in dict2.items():
# If the key is also found in the keys of the first dictionary, and...
if k in dict1.keys():
# If the value is a dictionary...
if isinstance(v, dict):
# we pass this value to the merge_and_add function, together with the value of first dictionary with
# the same key and we overwrite this value with the output.
dict1[k] = merge_and_add(dict1[k], v)
# If the value is an integer...
elif isinstance(v, int):
# we add the value of the key value pair of the second dictionary to the value of the first
# dictionary with the same key.
dict1[k] = dict1[k] + v
# If the key is not found, the key and value of the second should be appended to the first dictionary
else:
dict1[k] = v
# return the first dictionary
return dict1
I am trying the following but it isn't working:
df_curr_hist['latest'] = np.nan
def latest(df):
idx = 0
while idx < len(df):
curr_dict = df.iloc[idx]['current']
hist_dict = df.iloc[idx]['history']
df.latest[idx] = merge_and_add(curr_dict, hist_dict)
return df
Firstly, you should know that dictionaries are not passed as values in function arguments. Therefore, in your current code, modifications are made to original dictionaries when creating the new combined dictionary. You can handle that by using copies of the dictionaries to work with.
x = {'a':{'b':2}}
y = {'c':{'e':4}}
e = pd.DataFrame({'a':[x], 'b': [y]})
def merge_and_add(x, y):
dict1 = x.copy()
dict2 = y.copy()
# We loop over the key and value pairs of the second dictionary...
for k, v in dict2.items():
# If the key is also found in the keys of the first dictionary, and...
if k in dict1.keys():
# If the value is a dictionary...
if isinstance(v, dict):
# we pass this value to the merge_and_add function, together with the value of first dictionary with
# the same key and we overwrite this value with the output.
dict1[k] = merge_and_add(dict1[k], v)
# If the value is an integer...
elif isinstance(v, int):
# we add the value of the key value pair of the second dictionary to the value of the first
# dictionary with the same key.
dict1[k] = dict1[k] + v
# If the key is not found, the key and value of the second should be appended to the first dictionary
else:
dict1[k] = v
# return the first dictionary
return dict1
e['c'] = e.apply(lambda x : merge_and_add(x.a, x.b), axis = 1)
The final output looks like
a b c
0 {'a': {'b': 2}} {'c': {'e': 4}} {'a': {'b': 2}, 'c': {'e': 4}}

How to split list inside a dictionnary to create a new one?

I've been struggling on something for the day,
I have a dictionnary under the format
dict = {a:[element1, element2, element3], b:[element4, element5, element6]...}
I want a new dictionnary under the form
newdict = {a:element1, b:element4...}
Meaning only keeping the first element of the lists contained for each value.
You can use a dictionary comprehension:
{k: v[0] for k, v in d.items()}
# {'a': 'element1', 'b': 'element4'}
Hopefully this helps.
I like to check if the dictionary has a key before overwriting a keys value.
dict = {a:[element1, element2, element3], b:[element4, element5, element6]}
Python 2
newDict = {}
for k, v in dict.iteritems():
if k not in newDict:
# add the first list value to the newDict's key
newDick[k] = v[0]
Python 3
newDict = {}
for k, v in dict.items():
if k not in newDict:
# add the first list value to the newDict's key
newDick[k] = v[0]

Adding dictionary values to a list, which is a value to a dictionary

Im having a python dictionary which has value field as list.
I want to append to dictionary values to each list based on the key value.
How do i do it? I have one sample dictionary which i iterate and get values to append to the list. The code i wrote somehow seem to add all values in the sample dict to all key values in the dict im appending values to.
What am i doing wrong?
default_value = []
a = dict.fromkeys(li, default_value)
for key, value in data.items():
if key == "items":
for val in value:
a[val['owner']['display_name']].append(val)
a = dict.fromkeys([1, 2, 3], [])
creates a dictionary:
{1: [],
2: [],
3: []}
where all values point to the same dictionary.
a[1].append(5)
{1: [5],
2: [5],
3: [5]}
You have to create the dictionary in a real loop:
a = {k: [] for k in li}
Your code snippet could be written as:
a = {k: [] for k in li}
for val in data['items']:
a[val['owner']['display_name']].append(val)

Deleting from dict if found in new list in Python

Say I have a dictionary with whatever number of values.
And then I create a list.
If any of the values of the list are found in the dictionary, regardless of whether or not it is a key or an index how do I delete the full value?
E.g:
dictionary = {1:3,4:5}
list = [1]
...
dictionary = {4:5}
How do I do this without creating a new dictionary?
for key, value in list(dic.items()):
if key in lst or value in lst:
del dic[key]
No need to create a separate list or dictionary.
I interpreted "whether or not it is a key or an index" to mean "whether or not it is a key or a value [in the dictionary]"
it's a bit complicated because of your "values" requirement:
>>> dic = {1: 3, 4: 5}
>>> ls = set([1])
>>> dels = []
>>> for k, v in dic.items():
if k in ls or v in ls:
dels.append(k)
>>> for i in dels:
del dic[i]
>>> dic
{4: 5}
A one liner to do this would be :
[dictionary.pop(x) for x in list if x in dictionary.keys()]
dictionary = {1:3,4:5}
list = [1]
for key in list:
if key in dictionary:
del dictionary[key]
>>> dictionary = {1:3,4:5}
>>> list = [1]
>>> for x in list:
... if x in dictionary:
... del(dictionary[x])
...
>>> dictionary
{4: 5}
def remKeys(dictionary, list):
for i in list:
if i in dictionary.keys():
dictionary.pop(i)
return dictionary
I would do something like:
for i in list:
if dictionary.has_key(i):
del dictionary[i]
But I am sure there are better ways.
A few more testcases to define how I interpret your question:
#!/usr/bin/env python
def test(beforedic,afterdic,removelist):
d = beforedic
l = removelist
for i in l:
for (k,v) in list(d.items()):
if k == i or v == i:
del d[k]
assert d == afterdic,"d is "+str(d)
test({1:3,4:5},{4:5},[1])
test({1:3,4:5},{4:5},[3])
test({1:3,4:5},{1:3,4:5},[9])
test({1:3,4:5},{4:5},[1,3])
If the dictionary is small enough, it's easier to just make a new one. Removing all items whose key is in the set s from the dictionary d:
d = dict((k, v) for (k, v) in d.items() if not k in s)
Removing all items whose key or value is in the set s from the dictionary d:
d = dict((k, v) for (k, v) in d.items() if not k in s and not v in s)

Categories