why is name.startswith('a') returning True on the name 'barry'?

70 Views Asked by At

I am trying to learn how to use the .startswith() method and also the filter() function. For some reason I am not getting the result I expected. I don't know if I am misunderstanding 'startswith' or 'filter'.

here is the code i used

names = ['aaron','anthony','tom','henry','barry']
def start_a(names):
    for name in names:
        if name.startswith('a'):
            return True
            
            
        
print(list(filter(start_a, names)))

i was expecting to get ['aaron', 'anthony'] however i got ['aaron', 'anthony', 'barry']

does anyone know where i went wrong? thanks

2

There are 2 best solutions below

0
Barmar On BEST ANSWER

start_a() is looping over the characters in the name, because it just receives one list element as its parameter. So it's actually checking whether the name contains a, not whether it starts with a.

filter() does the looping over the list for you, you don't need another loop in the function.

def start_a(name):
    return name.startswith('a')
0
tdelaney On

filter calls start_a for each name in the names list. When you iterate that name in the for loop, you get individual characters, not the name. As a result, you return True for any name with an a in it. You can see that with a well-positioned print:

names = ['aaron','anthony','tom','henry','barry']
def start_a(names):
    print("start_a")
    for name in names:
        print("  checking", repr(name))
        if name.startswith('a'):
            print("TRUE!")
            return True          
        
print(list(filter(start_a, names)))    

Output

start_a
  checking 'a'
TRUE!
start_a
  checking 'a'
TRUE!
start_a
  checking 't'
  checking 'o'
  checking 'm'
start_a
  checking 'h'
  checking 'e'
  checking 'n'
  checking 'r'
  checking 'y'
start_a
  checking 'b'
  checking 'a'
TRUE!
['aaron', 'anthony', 'barry']

                             

You are checking a single name on each call to start_a, so rename that variable and remove the loop. Since you only call startswith once, you can also get rid of the if.

names = ['aaron','anthony','tom','henry','barry']
def start_a(name):
    return name.startswith('a')
           
            
        
print(list(filter(start_a, names)))

This is one of those cases where an anonymous function comes in handy. You could also write

names = ['aaron','anthony','tom','henry','barry']       
print(list(filter(lambda name: name.startswith('a'), names)))

You could also write it as a list comprehension

names = ['aaron','anthony','tom','henry','barry']       
print([name for name in names if name.startswith('a')])