Hello Stackoverflow people,
I have a nested dictionary with lists as values and I want to create a dict where all the list entries get their corresponding key as value.
Example time!
# what I have
dict1 = {"A":[1,2,3], "B":[4,5,6], "C":[7,8,9]}
# what I want
dict2 = {1:"A", 2:"A", 3:"A", 4:"B", 5:"B", 6:"B", 7:"C", 8:"C", 9:"C"}
Any help will be much appreciated!
Try this
dict1 = {"A":[1,2,3], "B":[4,5,6], "C":[7,8,9]}
dict2= {}
for keys,values in dict1.items():
for i in values:
dict2[i]=keys
print(dict2)
Output
{1: 'A', 2: 'A', 3: 'A', 4: 'B', 5: 'B', 6: 'B', 7: 'C', 8: 'C', 9: 'C'}
Hope it helps
Use dictionary comprehension:
d = {'a': 'b', 'c': 'd', 'e': 'f'}
d2 = dict((v1, k) for k, v in d.items() for v1 in v) # Here is the one-liner
assuming your key: value dictionary contains list as a value and using dict comprehension.
Using a second loop to iterate over the list present in original dictionary.
{item: key for key, value in dict1.items() for item in value}
Related
Take this for example:
d = {1: ['a', 'b', 'c'], 2: ['d', 'e', 'f'], 3: [1, 'i', 'j']}
I want to check if a value x exists inside of any of the lists in the dictionary, if it does, return the key of the list it's in.
So checking if 1 was in any of the lists in d, would return 3 (the key).
I know how to do this in the case that the dictionary values are not an iterable, but I'm having trouble figuring out how to do it when it is an iterable.
You can use list comprehension.
d = {1: ['a', 'b', 'c'], 2: ['d', 'e', 'f'], 3: [1, 'i', 'j']}
def ret_key_base_val(dct, val):
return [k for k,v in dct.items() if val in v]
result = ret_key_base_val(d, 1)
print(result)
# [3]
Using a list comprehension:
filtered_d = [k for k,v in d.items() if 1 in v]
for k, v for d.items() is your friend here, it will allow you easy access to both key and values in the context of your for-loop.
To support multiple types for v (making comprehensions tough to read/follow), then use type(v) and some if statements.
I need to combine two dictionaries by their value, resulting in a new key which is the list of keys with the shared value. All I can find online is how to add two values with the same key or how to simply combine two dictionaries, so perhaps I am just searching in the wrong places.
To give an idea:
dic1 = {'A': 'B', 'C': 'D'}
dic2 = {'D': 'B', 'E': 'F'}
Should result in:
dic3 = {['A', 'D']: 'B', 'C': 'D', 'E': 'F'}
I am not sure why you would need such a data structure, you can probably find a better solution to your problem. However, just for the sake of answering your question, here is a possible solution:
dic1 = {'A':'B', 'C':'D'}
dic2 = {'D':'B', 'E':'F'}
key_list = list(dic2.keys())
val_list = list(dic2.values())
r = {}
for k,v in dic1.items():
if v in val_list:
i = val_list.index(v) #get index at value
k2 = key_list[i] #use index to retrive the key at value
r[(k, k2)] = v #make the dict entry
else:
r[k] = v
val_list = list(r.values()) #get all the values already processed
for k,v in dic2.items():
if v not in val_list: #if missing value
r[k] = v #add new entry
print(r)
output:
{('A', 'D'): 'B', 'C': 'D', 'E': 'F'}
You can't assign a list as a key in a python dictionary since the key must be hashable and a list is not an ashable object, so I have used a tuple instead.
I would use a defaultdict of lists and build a reversed dict and in the end reverse it while converting the lists to tuples (because lists are not hashable and can't be used as dict keys):
from collections import defaultdict
dic1 = {'A':'B', 'C':'D'}
dic2 = {'D':'B', 'E':'F'}
temp = defaultdict(list)
for d in (dic1, dic2):
for key, value in d.items():
temp[value].append(key)
print(temp)
res = {}
for key, value in temp.items():
if len(value) == 1:
res[value[0]] = key
else:
res[tuple(value)] = key
print(res)
The printout from this (showing the middle step of temp) is:
defaultdict(<class 'list'>, {'B': ['A', 'D'], 'D': ['C'], 'F': ['E']})
{('A', 'D'): 'B', 'C': 'D', 'E': 'F'}
If you are willing to compromise from 1-element tuples as keys, the second part will become much simpler:
res = {tuple(value): key for key, value in temp.items()}
I have two dictionaries like below which have common keys:
dictionary1 = {1: 'a', 2: 'b' , 3: 'c'}
dictionary2 = {1: 'no', 2: 'yes' ,3:'yes'}
I want to create a new dictionary with the key and values of dictionary1 only if the corresponding values of the dictionary2 key has "yes".
Expected output:
{2: 'b', 3: 'c'}
What I have tried:
dictionary1 = {1: 'a', 2: 'b' , 3: 'c'}
dictionary2 = {1: 'no', 2: 'yes' ,3:'yes'}
common_pairs = dict()
for key,value in dictionary2.items():
for key,v in dictionary1.items():
if(value == "yes"):
common_pairs[key] = v
You don't need a nested for loop. Just a single iteration over dictionary1 items with corresponding O(1) lookup in dictionary2:
With a dict comprehension this would look like:
>>> dictionary1 = {1: 'a', 2: 'b' , 3: 'c'}
>>> dictionary2 = {1: 'no', 2: 'yes' ,3:'yes'}
>>> new = {k: v for k, v in dictionary1.items() if dictionary2[k] == 'yes'}
>>> new
{2: 'b', 3: 'c'}
With a traditional for loop:
>>> new = {}
>>> for k, v in dictionary1.items():
... if dictionary2[k] == 'yes':
... new[k] = v
...
>>> new
{2: 'b', 3: 'c'}
You could do this in a dictionary comprehension:
common_pairs = { key:value for key,value in dictionary1.items()
if dictionary2.get(key,"") == "Yes" }
The get function provides a default value if the key is not present. this will prevent errors if a key in dictionary1 is absent from dictionary2.
You can just iterate through dict2, check if the element is in dict1 and that the key is yes, and then add it to the dictionary.
dictionary1 = {1: 'a', 2: 'b' , 3: 'c'}
dictionary2 = {1: 'no', 2: 'yes' ,3:'yes'}
common_pairs = dict()
for key in dictionary2:
if key in dictionary1 and dictionary2[key] == 'yes':
common_pairs[key] = dictionary1[key]
I need to make sure I don't have more than one of the same keys, if so, leave the first one and add their value (make it a list) to the existing key
this is what I tried:
my_dict = {1: "A", 2: "B", 1: "C"}
new_dict={}
list_keys = list(my_dict.keys())
list_values = list(my_dict.values())
for i in range(len(list_values)):
if list_keys[i] in new_dict.keys():
new_dict[list_keys[i]].append(list(list_values[i]))
else:
new_dict.update({list_keys[i]: list_values[i]})
return new_dict
The result required:
{1: ["A", "C"], 2: ["B"]}
The most concise way of reversing a dict like that uses a defaultdict:
from collections import defaultdict
d = {"A": 1, "B": 2, "C": 1}
rev = defaultdict(list)
for k, v in d.items():
rev[v].append(k)
rev
# defaultdict(<class 'list'>, {1: ['A', 'C'], 2: ['B']})
That first line doesn't make sense. A dictionary cannot have two values for the same key, so when you run that first line, the resulting dictionary is:
my_dict = {1: 'A', 2: 'B', 1: 'C'}
print(my_dict)
# {1: 'C', 2: 'B'}
What you could do is iterate over lists of desired keys and values, and build the dictionary that you want that way:
my_keys = [1, 2, 1]
my_vals = ['A', 'B', 'C']
my_dict = {}
for k, v in zip(my_keys, my_vals):
if k in my_dict.keys():
if not isinstance(my_dict[k], list):
my_dict[k] = [my_dict[k]] # convert to a list
my_dict[k].append(v)
else:
my_dict[k] = v
print(my_dict)
# {1: ['A', 'C'], 2: 'B'}
Based on the comments, you originally had a dictionary in_dict = {'A': 1, 'B': 2, 'C':1}. Given this in_dict, you can get the desired result by setting my_keys = in_dict.values() and my_vals = in_dict.keys() in the code above.
Using comprehensions if you want
a = {"A":1, "B":2, "C":1}
{value: [item_[0] for item_ in a.items() if item_[1] == value] for value in set(a.values())}
Output
{1: ['A', 'C'], 2: ['B']}
The following is my dictionary and I need to check if I have repeated key or Value
dict = {' 1': 'a', '2': 'b', '3': 'b', '4': 'c', '5': 'd', '5': 'e'}
This should return false or some kind of indicator which helps me print out that key or value might be repeated. It would be much appreciated if I am able to identify if a key is repeated or a Value (but not required).
Dictionaries can't have duplicate keys, so in case of repeated keys it only keeps the last value, so check values (one-liner is your friend):
print(('There are duplicates' if len(set(dict.values()))!=len(values) else 'No duplicates'))
Well in a dictionary keys can't repeat so we only have to deal with values.
dict = {...}
# get the values
values = list(dict.values())
And then you can use a set() to check for duplicates:
if len(values) == len(set(values)): print("no duplicates")
else: print("duplicates)
It's not possible to check if a key repeats in a dictionary, because dictionaries in Python only support unique keys. If you enter the dictionary as is, only the last value will be associated with the redundant key:
In [4]: dict = {' 1': 'a', '2': 'b', '3': 'b', '4': 'c', '5': 'd', '5': 'e'}
In [5]: dict
Out[5]: {' 1': 'a', '2': 'b', '3': 'b', '4': 'c', '5': 'e'}
A one-liner to find repeating values
In [138]: {v: [k for k in d if d[k] == v] for v in set(d.values())}
Out[138]: {'a': [' 1'], 'b': ['2', '3'], 'c': ['4'], 'e': ['5']}
Check all the unique values of the dict with set(d.values()) and then creating a list of keys that correspond to those values.
Note: repeating keys will just be overwritten
In [139]: {'a': 1, 'a': 2}
Out[139]: {'a': 2}
What about
has_dupes = len(d) != len(set(d.values()))
I'm on my phone so I cant test it. But j think it will work.
Well, although key value should be unique according to the documentation, there is still condition where repeated key could appear.
For example,
>>> import json
>>> a = {1:10, "1":20}
>>> b = json.dumps(a)
>>> b
'{"1": 20, "1": 10}'
>>> c = json.loads(b)
>>> c
{u'1': 10}
>>>
But in general, when python finds out there's conflict, it takes the latest value assigned to that key.
For your question, you should use comparison such as
len(dict) == len(set(dict.values()))
because set in python contains an unordered collection of unique and immutable objects, it could automatically get all unique values even when you have duplicate values in dict.values()