A. Stanley
A. Stanley

Reputation: 17

Alternatives to index()

So for my project I have to allow the user to input a sentence and then input a word and find all the occourunces of the word and print the numbers. Here's what I have

    found = 0

sen = input("Enter the sentence you would like to break down!")
sen1 = sen.upper()
list = sen1.split()


search=input("Enter the word you want to search")
search1 = search.upper()
for search1 in list:
    found = found + 1

position=list.index(search1)



if position == 0:
    print("First word in the sentence")
if position == 1:
    print("Second word in the sentence")
if position == 2:
    print("Third word in the sentence")
if position == 3:
    print("Fourth word in the sentence")
if position == 4:
    print("Fifth word in the sentence")
if position == 5:
    print("6th word in the sentence")

else:
    position1 = position + 1
    print(position1, "th word in the sentence")

but it only prints the first occurunce of the word and rarely works. Any solutions?

Upvotes: 1

Views: 3896

Answers (3)

PM 2Ring
PM 2Ring

Reputation: 55469

Several comments have mentioned the danger of using list as a variable name. It's not actually a reserved word, but it is the name of a built-in type, and shadowing it by using it as a variable name can lead to mysterious bugs if you later wish to use this type to construct a list or test the type of an object.

A major problem with the code you posted is here:

search1 = search.upper()
for search1 in list:

The first line saves the upper-case version of the string search to the name search1. But the next line simply clobbers that with the words in list; it does not perform any searching operation. At the end of the for loop, search1 will be equal to the last item in list, and that's why your code isn't doing what you expect it to when it executes position=list.index(search1): you're telling it to find the position of the last word in list.


You could use .index to do what you want. To find multiple occurences you need to use a loop and pass .index a starting position. Eg,

def find_all(wordlist, word):
    result = []
    i = 0
    while True:
        try:
            i = wordlist.index(word, i) + 1
            result.append(i)
        except ValueError:
            return result

However, there's really not much benefit in using .index here..index performs its scan at C speed, so it's faster than scanning in a Python loop but you probably won't notice much of a speed difference unless the list you're scanning is large.

The simpler approach is as given in Tomasz's answer. Here's a variation I wrote while Tomasz was writing his answer.

def ordinal(n):
    k = n % 10
    return "%d%s" % (n, "tsnrhtdd"[(n // 10 % 10 != 1) * (k < 4) * k::4])

def find_all(wordlist, word):
    return [i for i, s in enumerate(wordlist, 1) if s == word]

sen = 'this has this like this'
wordlist = sen.upper().split()

words = 'this has that like'
for word in words.split():
    pos = find_all(wordlist, word.upper())
    if pos:
        pos = ', '.join([ordinal(u) for u in pos])
    else:
        pos = 'Not found'
    print('{0}: {1}'.format(word, pos))

output

this: 1st, 3rd, 5th
has: 2nd
that: Not found
like: 4th      

The code for ordinal was "borrowed" from this answer.

Upvotes: 0

Idos
Idos

Reputation: 15310

You have a great alternative which is re.finditer:

import re
sen = input("Enter the sentence you would like to break down!")
search = input("Enter the word you want to search")
for match in re.finditer(search, sen):
    print (match.start())

Upvotes: 0

Tomasz Jakub Rup
Tomasz Jakub Rup

Reputation: 10680

Replace list with a_list.

List of positions of a search1 occurances:

positions = [idx for idx, el in enumerate(a_list) if el == search1]

Upvotes: 2

Related Questions