5

I have a problem adding a value to a set which is a value in a dictionary. I have to use sets as values not list or anything else. I have seen this thread but it does not full ansver me.

from collections import defaultdict
datoteka = open("vzorec.list","rt")
slovar = defaultdict(set)

for vrstica in datoteka:
    seznam = vrstica.split("\t")
    naslov = seznam[0]
    beseda = seznam[len(seznam)-1]
    beseda = beseda.strip()
    naslov2 = ""
    for crka in naslov:
        if crka == "(":
            break
        else:
            naslov2 = naslov2 + crka
    naslov = naslov2.lstrip('"')

    if naslov not in slovar:
        slovar[naslov] = set(beseda)

    elif naslov in slovar:
        slovar[naslov] = slovar[naslov].add(beseda)



print(slovar)

I get an error that a string type does not have an add function. But why does python not understand that I want to have sets as values. I even used the defaultdict

Community
  • 1
  • 1
HRIbar
  • 51
  • 1
  • 1
  • 3
  • @hochl: Actually I think using a `defaultdict` is more elegant. – Niklas B. Aug 21 '12 at 13:06
  • @hochl -- `defaultdict` is definitely more elegant (and probably more efficient) as it doesn't create an unnecessary set at every iteration through the loop. – mgilson Aug 21 '12 at 13:08

2 Answers2

8

You just want:

slovar[naslov].add(beseda)

instead of:

if naslov not in slovar:
    slovar[naslov] = set(beseda) # set of characters in beseda string ???

elif naslov in slovar:
    slovar[naslov] = slovar[naslov].add(beseda) # add to the set, returns None ???

This works because with a defaultdict, if the key isn't present, it adds an empty set as the value to that particular key and returns it empty set. So, the first time around, slovar[naslov] returns an empty set which you then .add(beseda).

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • 3
    If `beseda` is a string, then `set(beseda)` will return a set of individual characters, while `slovar[naslov].add(beseda)` will insert a full string into an existing set. One of these two behaviors is probably not desired here. – senderle Aug 21 '12 at 13:04
  • 1
    Yep, probably OP means either `set((besada,))` or `.extend(beseda)` – Niklas B. Aug 21 '12 at 13:06
  • Seeing that "naslov" means "address" and "slovar" means "dictionary" and "beseda" means "word", I think that the first one is more likely. – Niklas B. Aug 21 '12 at 13:11
  • 1
    @NiklasB. -- It looks like we're both using google translate. Anyway, my money's on the first one too. I don't know why I said second in my previous comment (I'll blame it on a bit-flip in my brain)... – mgilson Aug 21 '12 at 13:13
5

Python understands fine :). You have a bug in your code.

set.add mutates the set and returns None, so you've discarded your set and set the key to None. You just want to do slovar[naslov].add(beseda) whether naslov is or isn't in the set, and not care about the return value.

I don't see how a string would be getting in there, so if that doesn't solve your issue, you need to paste a full traceback.

Julian
  • 3,375
  • 16
  • 27