简体   繁体   中英

python- searching dictionary sublists; converting dictionary keys to values

Say I have the following dictionary (the one I'm using is much, much larger):

dict1={1:["item", "word", "thing"], 2:["word", "item"], 3:["thing", "item", "item"]}

and have every word used in the dictionary stored in a list:

all_words=["item", "word", "thing"]

I want to run each word of the list through the dictionary sublists, and return the keys for all sublists in which they are found, storing them in tuples. So I want to get:

dict2={"item":(1, 2, 3), "word":(1, 2), "thing":(1, 3)}

heres what I have:

dict2={}    
for word in all_words:
    for key, sublist in dict2.items():
        for word in sublist:
            if word not in sublist:
                dict2[word]=dict2[word]+key
            else:
                dict2[word]=key

So, your fixed program, based on the comments would look like this

>>> dict2 = {}
>>> for word in all_words:
...     # Iterate over the dict1's items
...     for key, sublist in dict1.items():
...         # If the word is found in the sublist
...         if word in sublist:
...             # If the current word is found in dict2's keys
...             if word in dict2:
...                 # Append the current key as a one element tuple
...                 dict2[word] += (key,)
...             else:
...                 # Create a one element tuple and assign it to the word
...                 dict2[word] = (key,)
... 
>>> dict2
{'item': (1, 2, 3), 'word': (1, 2), 'thing': (1, 3)}

If you know about dictionary comprehension, then the same can be written as

>>> {word: tuple(k for k, v in dict1.items() if word in v) for word in all_words}
{'item': (1, 2, 3), 'word': (1, 2), 'thing': (1, 3)}

The whole tuple creation logic, based on the dict1 for every corresponding word , has been squeezed as a single generator expression and converted to a tuple with tuple(k for k, v in dict1.items() if word in v)

Your code's logic is incorrect, because you are iterating over 3 objects while you just need to iterate over your dictionary and revers the position of key and values but as you may have duplicated values you can use a set container for preserving the corresponding keys for each name. dict.setdefault is a great tool for this such situations:

>>> d={}
>>> for i,j in dict1.items():
...    for k in j:
...      d.setdefault(k,set()).add(i)
... 
>>> d
{'item': set([1, 2, 3]), 'word': set([1, 2]), 'thing': set([1, 3])}

Problem is you are looping dict2.items whereas it should be dict1.items . Also you are not appending the keys into the dict2 values if found, you just reassign the values to the last key found in dict1 values. Thus the dict2 values are not what you expected.

Instead you can alternatively use collections.defaultdict (or use solution from @Kasra, @thefourtheye):

from collections import defaultdict

dict2 = defaultdict(tuple)

for word in all_words:
    for key, sublist in dict1.iteritems(): # this 
        if word in sublist:
            dict2[word] += (k,)
        else:
            dict2[word] = (k,)

dict2
Out[3]: defaultdict(<type 'tuple'>, {'item': (1, 2, 3), 'word': (1, 2), 'thing': (1, 3)})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM