-2

Hello i have a list of words that I want to check against a dictionary with keys and values. Actually I just want to know if some of the words in the list appear in the values of the dictionary. This is probably a ver easy task in python, but I am a beginner and I just keep getting the same error that I obviously don't understand.

Here is my code (the dict is at hand ):

words = ["give", "a", "pearl", "to", "the" "elephant"]

for k, v in dic.items():
    for word in words:
        if word in v: 
            print(v)

or alternatively:

relevant = {d:reldic[d] for d in reldic if words in reldic[d]}
print(relevant)

the error I get:

TypeError: unhashable type: 'list'

What is missing?

Thanks in advance!

Update:

Ok, this help to understand the question better. That how my data looks like:

2000/9/1    abe D   mes Español inan.|m.|m.
2000/9/1    abe D   luna    Español inan.|m.|m.
2000/9/1    abe D   sol Español inan.|m.|m.
2000/9/2    gacuri  D   meter   Español v.t.
2000/9/2    acuri   D   meter   Español v.t.
2000/9/2    yacuri  D   meter   Español v.t.

Then I have a collection of relevant blocks:

dic = collections.defaultdict(set)

for e in entries:
    dic[e[1]].add(e[3])

and lastly my dictionary:

reldic = {d:dic[d] for d in dic if len(dic[d]) > 1}
El_Patrón
  • 533
  • 1
  • 10
  • 24
  • you are probably trying to use a list as a dict key, which is not allowed – wim Oct 11 '14 at 13:21
  • Sorry, is not "reldic" just "dict", is updated – El_Patrón Oct 11 '14 at 13:22
  • This question was caused by a problem that can no longer be reproduced or a simple typographical error. While similar questions may be on-topic here, this one was resolved in a manner unlikely to help future readers. This can often be avoided by identifying and closely inspecting the [shortest program necessary to reproduce the problem](http://stackoverflow.com/help/mcve) before posting. – thefourtheye Oct 11 '14 at 13:23
  • are you trying to make dict or just get the common words? Also adding an example of dic may help – Padraic Cunningham Oct 11 '14 at 13:27
  • I am trying to get the words in the list from the dictionary. See my update, I hope this help to understand the question. – El_Patrón Oct 11 '14 at 13:47

2 Answers2

2

That specific error is telling you that you can't use a list (or anything else that's not 'hashable') as a key for a dictionary. As an example:

# all of the following are ok
d = dict()
d[3] = True
d['text'] = True
d[(3, 'text')] = True

a_list = []
d[a_list] = 'ok?'  # this is not ok

The first version of your code is fine so you can use that. It looks like you're trying to do it using a dictionary comprehension but what you have is a little non-sensical.

The closest, tersest code to what you're written is probably something like:

relevant = {k:v for k,v in dic.items() if any(filter(lambda w: w in v, words))}

But it's certainly a strange non-obvious thing to read. Honestly, I'd go with your first code sample and read up a bit more on dictionary comprehensions to get a better idea of where they should be used.

EDIT: Now we have the data itself we can solve this a little better. Let's start using the format you have:

dic = {'abe': {'luna', 'mes', 'sol'},
       'acuri': {'meter'},
       'gacuri': {'meter'},
       'yacuri': {'meter'}}

We can use set operations to make this more efficient (depending on various sizes of data etc, you'd have to test).

words = ["give", "a", "pearl", "to", "the", "meter"]
ws = set(words)
[k for k,v in dic.items() if v.intersection(ws)]
# ['acuri', 'gacuri', 'yacuri']

But really, that's all a bit backwards as you have to loop over your whole index, which partially defeats the point of an index in the first place. It looks to me that you want to create your index in the reverse direction to start with.

dic = collections.defaultdict(set)
for e in entries:
    dic[e[3]].add(e[1])

# note, we're now mapping from word -> book(?)
dic = {'mes': {'abe'},
       'sol': {'abe'},
       'meter': {'acuri', 'gacuri', 'yacuri'},
       'luna': {'abe'}}

# now it's simple and efficient to find all the books that contain the words
sets_of_books_containing_words = [dic[w] for w in words if w in dic]

# and to combine that together into a single set
books_containing_one_of_the_words = set.union(*sets_of_books_containing_words)
Aidan Kane
  • 3,856
  • 2
  • 25
  • 28
  • Thanks @Aidan Kane, I understand that a list cannot be a key in a dictionary, but I have a list of words that I want to check over the dictionary, I am not trying to use a list as a key. I hope I understood you right! – El_Patrón Oct 11 '14 at 13:31
  • Yes, I see. The first part of my code still produce the error: 'TypeError: unhashable type: 'list''. I just checked and the 'v' has the type 'set()', is this may be the problem? – El_Patrón Oct 11 '14 at 13:37
  • Regarding the reading more part, here is a question that is not directly related but has some good reading material in the answers and links:http://stackoverflow.com/questions/9010222/how-can-python-dict-have-multiple-keys-with-same-hash . I'm also voting you up. – eri0o Oct 11 '14 at 13:40
  • Ah ok, set is also unhashable (because it can change). Let me add a little more info since I can now see the data you're using. – Aidan Kane Oct 11 '14 at 14:55
-2

d is list. And list can't be a key in dictionary.

Darth Kotik
  • 2,261
  • 1
  • 20
  • 29