0

I am trying list out all matches of an element in a list. But getting it wrong. whats wrong in below code.

theList = ['a','e','i','o','u','e','o','e']

def matchall1(theList, value, pos=0):
    loc = pos - 1
    try:
        loc = theList.index(value, loc+1)
        yield loc
    except ValueError:
        pass

value = 'e'
for loc in matchall1(theList, value):
    print("match at", loc+1, "position.")

Result i am getting from above code is just ¨match at 2 position.¨

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
  • 2
    Considering that we already have 2 deleted answers with a score of -1 that both misunderstood the problem, I think we have to ask for a [mcve]. – Aran-Fey Sep 11 '18 at 11:55
  • Your function `yield`s just one time. You need to use a loop (or recursion). – Gabriel Sep 11 '18 at 11:56
  • You can find several solutions to your problem among the answers to this question: https://stackoverflow.com/questions/176918/finding-the-index-of-an-item-given-a-list-containing-it-in-python?rq=1 – jpw Sep 11 '18 at 11:59
  • @Aran-Fey I am calling the method matchall1 in a loop, right? so it should proceed to search for the next occurrence from the loc+1 location? – arun chakravarthy Sep 11 '18 at 12:00
  • 1
    @arunchakravarthy No, you're not actually calling it in a loop. You're running a loop that depends on its result. It should have a loop and generate *all* the results on its own. See my answer. – iBug Sep 11 '18 at 12:42

6 Answers6

2

That might be as simple as that you forgot the loop:

def matchall1(theList, value, pos=0):
    loc = pos - 1
    try:
        while True:  # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            loc = theList.index(value, loc+1)
            yield loc
    except ValueError:
        pass

value = 'e'
for loc in matchall1(theList, value):
    print("match at", loc+1, "position.")

Output:

match at 2 position.
match at 6 position.
match at 8 position.
iBug
  • 35,554
  • 7
  • 89
  • 134
1

If you want to find all matches, you'll need some form of repetition (iterative loop or recursion).

Judging by the signature of your function your intention was to use recursion, which would look like:

def matchall_version1(theList, value, i=0):
    try:
        i = theList.index(value, i)
        yield i
        yield from matchall_version1(theList, value, i+1)
    except ValueError:
        pass

And using a loop your code would look like:

def matchall_version2(theList, value):
    i = 0
    try:
        while True:
            i = theList.index(value, i + 1)
            yield i
    except ValueError:
        pass

However I'd like to suggest this other version, which is far more readable than yours imho:

def matchall_version3(theList, value):
    for i, x in enumerate(theList):
        if x == value:
            yield i

All three versions yield to the same result. This:

theList = ['a','e','i','o','u','e','o','e']
print(list(matchall_version1(theList, 'e')))
print(list(matchall_version2(theList, 'e')))
print(list(matchall_version3(theList, 'e')))

Prints this:

[1, 5, 7]
[1, 5, 7]
[1, 5, 7]
Gabriel
  • 1,922
  • 2
  • 19
  • 37
0

You can do it by a list comprehension

[index for index, letter in enumerate(theList) if letter==value]
blue_note
  • 27,712
  • 9
  • 72
  • 90
0

The algorithm is a bit confusing, better use a generator expression:

theList = ['a','e','i','o','u','e','o','e']
def matchAll(element, lst):
    yield from (i for i, e in enumerate(lst) if e == element)

Here you have the live example

Netwave
  • 40,134
  • 6
  • 50
  • 93
0

I won't get into the technicalities of the kind of question you ask, instead I'll give you an answer that might help you solve your problem.

theList = ['a','e','i','o','u','e','o','e']

def matchall1(theList, value, pos=0):
    loc = pos - 1
    try:
        for items in theList:  #ADD THIS TO YOUR CODE AND YOU'LL BE GOOD
            loc = theList.index(value, loc+1)
            yield loc
    except ValueError:
        pass

value = 'e'
for loc in matchall1(theList, value):
    print("match at", loc+1, "position.")

This gives you a comprehensive output, i.e one at a time. If you want all the positions in the same output statement then I'd suggest you to add it to a list and then pass it in the for loop implemented later.

EDIT 1: I've quicky added the part where you can output all the positions in the same statement. The code might look nasty, and Not-Professional, but it works. Take a look at it

theList = ['a','e','i','o','u','e','o','e']

def matchall1(theList, value, pos=0):
    loc_list = []
    loc = pos - 1
    try:
        for items in theList:
            loc = theList.index(value, loc+1)
            loc_list.append(loc)
            yield loc_list
    except ValueError:
        pass

value = 'e'
for loc in matchall1(theList, value):
    continue
new_loc = []
for x in loc:
    x+=1
    new_loc.append(x)

pos = ",".join(str(x) for x in new_loc)

print("Match at", pos, "position.")

Output:

Match at 2,6,8 position.
Devanshu Misra
  • 773
  • 1
  • 9
  • 28
-1
theList = ['a','e','i','o','u','e','o','e']

def matchall1(theList, value, pos=0):
    loc = pos - 1
    loc = [i for i, v in enumerate(theList) if v == value]
    for p in loc:
        yield p

value = 'e'
for loc in matchall1(theList, value):
    print("match at", loc+1, "position.")
Y.Wang
  • 153
  • 5