19

I wrote this code to perform as a simple search engine in a list of strings like the example below:

mii(['hello world','hello','hello cat','hellolot of cats']) == {'hello': {0, 1, 2}, 'cat': {2}, 'of': {3}, 'world': {0}, 'cats': {3}, 'hellolot': {3}}

but I constantly get the error

'dict' object has no attribute 'add'

how can I fix it?

def mii(strlist):
    word={}
    index={}
    for str in strlist:
        for str2 in str.split():
            if str2 in word==False:
                word.add(str2)
                i={}
                for (n,m) in list(enumerate(strlist)):
                    k=m.split()
                    if str2 in k:
                        i.add(n)
                index.add(i)
    return { x:y for (x,y) in zip(word,index)}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
stt
  • 321
  • 1
  • 2
  • 4

4 Answers4

60

In Python, when you initialize an object as word = {} you're creating a dict object and not a set object (which I assume is what you wanted). In order to create a set, use:

word = set()

You might have been confused by Python's Set Comprehension, e.g.:

myset = {e for e in [1, 2, 3, 1]}

which results in a set containing elements 1, 2 and 3. Similarly Dict Comprehension:

mydict = {k: v for k, v in [(1, 2)]}

results in a dictionary with key-value pair 1: 2.

sirfz
  • 4,097
  • 23
  • 37
5
x = [1, 2, 3] # is a literal that creates a list (mutable array).  
x = []  # creates an empty list.

x = (1, 2, 3) # is a literal that creates a tuple (constant list).  
x = ()  # creates an empty tuple.

x = {1, 2, 3} # is a literal that creates a set.  
x = {}  # confusingly creates an empty dictionary (hash array), NOT a set, because dictionaries were there first in python.  

Use

x = set() # to create an empty set.

Also note that

x = {"first": 1, "unordered": 2, "hash": 3} # is a literal that creates a dictionary, just to mix things up. 
TarangP
  • 2,711
  • 5
  • 20
  • 41
DragonLord
  • 6,395
  • 4
  • 36
  • 38
1

I see lots of issues in your function -

  1. In Python {} is an empty dictionary, not a set , to create a set, you should use the builtin function set() .

  2. The if condition - if str2 in word==False: , would never amount to True because of operator chaining, it would be converted to - if str2 in word and word==False , example showing this behavior -

    >>> 'a' in 'abcd'==False
    False
    >>> 'a' in 'abcd'==True
    False
    
  3. In line - for (n,m) in list(enumerate(strlist)) - You do not need to convert the return of enumerate() function to list, you can just iterate over its return value (which is an iterator directly)

  4. Sets do not have any sense of order, when you do - zip(word,index) - there is no guarantee that the elements are zipped in the correct order you want (since they do not have any sense of order at all).

  5. Do not use str as a variable name.

Given this, you are better off directly creating the dictionary from the start , rather than sets.

Code -

def mii(strlist):
    word={}
    for i, s in enumerate(strlist):
        for s2 in s.split():
            word.setdefault(s2,set()).add(i)
    return word

Demo -

>>> def mii(strlist):
...     word={}
...     for i, s in enumerate(strlist):
...         for s2 in s.split():
...             word.setdefault(s2,set()).add(i)
...     return word
...
>>> mii(['hello world','hello','hello cat','hellolot of cats'])
{'cats': {3}, 'world': {0}, 'cat': {2}, 'hello': {0, 1, 2}, 'hellolot': {3}, 'of': {3}}
Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
0
def mii(strlist):
    word_list = {}
    for index, str in enumerate(strlist):
        for word in str.split():
            if word not in word_list.keys():
                word_list[word] = [index]
            else:
                word_list[word].append(index)
    return word_list

print mii(['hello world','hello','hello cat','hellolot of cats'])

Output:

{'of': [3], 'cat': [2], 'cats': [3], 'hellolot': [3], 'world': [0], 'hello': [0, 1, 2]}

I think this is what you wanted.

Morishiri
  • 874
  • 10
  • 23