Python Dictionary: Compare keys with Values of All Keys
Solution 1
Try with:
test_dict = {'bat': [['gum', 'glove', 'knee']],
'crowd': [['big', 'nice', 'large']],
'glove': [['mitt', 'ball', 'bat']]}
def find_matches(dict1):
match_dict = {}
base_keys = dict1.keys()
for key, values in dict1.items():
for words in values:
for base_key in base_keys:
if base_key in words:
match_dict.update({key: base_key})
return match_dict
print(find_matches(test_dict)) #{'bat': 'glove', 'glove': 'bat'}
Multiple for
is because you have a [['mitt', 'ball', 'bat']]
bidimensional list.
Maybe is more clear using set
EDIT
You post the antoher example dict without bidemensional values in dict, the sol is simple, delete a for
like:
test_dict={'cubed': ['zryba', 'aszcb', 'btadc', 'melon', 'ewdgf'],
'melon': ['jbilk', 'kcjml', 'cubed', 'nfmpo', 'ognqp'],
'poop': ['mllm', 'nmmn', 'onno', 'qppq', 'rqqr']}
def find_matches(dict1):
match_dict = {}
base_keys = dict1.keys()
for key, values in dict1.items():
for base_key in base_keys:
if base_key in values:
match_dict.update({key: base_key})
return match_dict
print(find_matches(test_dict)) #{'cubed': 'melon', 'melon': 'cubed'}
Solution 2
The following works for me:
test_dict={'cubed': ['melon', '2', '3', '4', '5'],
'melon': ['2', 'poop', '4', '5', '6'],
'poop': ['3', '4', '5', '6', 'cubed']}
d = defaultdict(str)
# iterate over keys and values
for key, values in test_dict.items():
# iterate over values
for val in values:
# if val is a key
if val in [x for x in test_dict.keys() if x != key]:
# set dict[key] = val
d[key] = val
print(d)
defaultdict(<class 'str'>, {'melon': 'poop', 'poop': 'cubed', 'cubed': 'melon'})
Essentially, you check all the values against the list of keys, excluding the current key. If you want the returned dict to contain more than one value, use lists or sets:
defaultdict(list) or defaultdict(set)
and append the values
d[key].append(val) or d[key].add(val)
Solution 3
You can actually solve this problem with a dict comprehension. You just need to iterate over the names and lists in test_dict
until you find a name which is both in the dict and a list:
>>> {n1:n2 for n1 in test_dict for n2 in test_dict[n1] if n2 in test_dict}
{'cubed': 'melon', 'melon': 'cubed'}
Solution 4
If your problem statement is correct, then your trouble lies in the fact that your test_dict
is a dictionary mapping strings to lists of lists instead of mapping them to a list of words.
Your find_matches
function iterates over the dictionary, placing the string key into key
and the list-of-lists-of-words into value
.
You then try to iterate over value
. But of course if value
is set to
[['gum', 'glove', 'knee']]
then when you do
for word in value:
the variable word
will take on the value ['gum', 'glove', 'knee']
and then the loop will end, because value
only contains one element - a sublist of three words.
You can confirm this by printing key
and then printing each word
in your loop - I expect you will only see one line, with a list of words.
To fix this, ideally you would change the format of your dictionary. Why store a list of 1 list of words? Why not just store a list-of-words directly?
If that is impossible for some reason, then you will need to decide how to proceed: if there are more than one list-of-words, do you want to scan them all, or only the first such list?
# Scan the first list:
for word in value[0]:
...
# Scan all the lists:
for sublist in value:
for word in sublist:
...
Related videos on Youtube
Z_D
Updated on June 04, 2022Comments
-
Z_D almost 2 years
I am working through a problem that requires me to compare elements in a dictionary containing words as keys and lists of words as values. See example below.
test_dict={'cubed': ['zryba', 'aszcb', 'btadc', 'melon', 'ewdgf'], 'melon': ['jbilk', 'kcjml', 'cubed', 'nfmpo', 'ognqp'], 'poop': ['mllm', 'nmmn', 'onno', 'qppq', 'rqqr']}
I would like to return a new dictionary which contains keys that match the values of other keys in the dictionary. My code below is incorrect, I think because it is only considering each key-value pair independently and comparing items within those pairs only. Is there a way to iterate across keys to get the desired result? My desired result is shown below.
def find_matches(dict1): match_dict={} for key, value in dict1.items(): for word in value: if key == word: #rotate_dict[key]=word match_dict[key].append(word) return match_dict find_matches(SO_example) #returns {}, but should return {'cubed':'melon','melon':'cubed'}
Thank you for your help.
-
Jon Clements over 6 yearsUmm... well
{k:v for k, values in test_dict.items() for v in values[0] if v in test_dict}
should do it - but do you really have a one-element list containing a list? -
Z_D over 6 yearsNo, my test example was wrong - apologies. Please see edit above.
-
Jon Clements over 6 yearsI'm now confused what you want... You're using
.append
but don't have a list, but your output example cites a normaldict
... what would the output be for the above?
-
-
Z_D over 6 yearsI think my test example is incorrect. The output of my real result is now above.
-
Z_D over 6 yearsThank you! Per my question I'm clearly a beginner, so didn't think of the nice update method you used. Appreciate your help and the edit after I fixed the example.