Two versions, return opposite answers, but always one comes out wrong. I'm not sure where I've gone wrong. I've tried a series of other options, but this seems to get the closest. EDIT: Needs to be in a loop
goals: identify element in list, identify when element is not in list, identify when list is [], return strings accordingly.
def search_for_string(a_list, search_term):
i=0
for search_term in a_list:
i += 1
if a_list[i] == search_term:
return 'string found!'
elif a_list[i] != search_term:
return 'string not found2'
if len(a_list) == 0:
return 'string not found'
apple = search_for_string(['a', 'b', 'c'], 'd')
print(apple)
def search_for_string(a_list, search_term):
i=0
for search_term in a_list:
if a_list[i] == search_term:
return 'string found!'
elif a_list[i] != search_term:
return 'string not found2'
i += 1
if len(a_list) == 0:
return 'string not found'
apple = search_for_string(['a', 'b', 'c'], 'd')
print(apple)
other tests:
apple = search_for_string(['a', 'b', 'c'], 'b')
apple = search_for_string([], 'b')
8 Answers 8
Python makes your life super easy for this sort of thing:
def search_for_string(a_list, search_term):
if search_term in a_list:
return 'string found!'
return 'string not found'
Comments
There are few things wrong and Non-Pythonic in your code:
def search_for_string2(a_list, search_term):
i=0 # <----- Not Pythonic! If you want to get index we use enumerate(a_list)
for search_term in a_list: # <--- search_term passed to function is lost and gets overwritten by elements in a_list.
i += 1 # <--- Not Pythonic in this context
if a_list[i] == search_term: #<--- a_list[index+1] == a_list[index]. True if consecutive elements are same else False!
return 'string found!' #<--- No WRONG!, You didn't find the string, Consecutive elements are same!
elif a_list[i] != search_term:
return 'string not found2' #<-- Consecutive elements are not same!
if len(a_list) == 0:
return 'string not found'
According to the goals you have defined you can implement it like so:
def search_for_string(alist, search_term):
if not alist:
return "List is empty"
if search_term in alist:
return "First occurence of string Found at index position: " + str(alist.index(search_term))
else:
return "String not found"
print(search_for_string(['a', 'b', 'c'], 'd'))
print(search_for_string(['a', 'b', 'c'], 'b'))
print(search_for_string([], 'b'))
Output:
String not found
First occurence of string Found at index position: 1
List is empty
Comments
The short answer is that the return for != does not do what you think it does and that lists are 0-indexed not 1-indexed. The code is actually much simpler than you think:
def search_for_string(haystack, needle):
if not haystack: # check for empty list
return 'List was empty!'
for x in haystack:
if needle == x:
return 'String found!'
return 'String not found!'
Essentially, you only know if a string was not found if you’ve gone through and checked each element at least once. But you know if a string was found, well, when you find it.
Now to explain the issues with your code:
This version does not work because (1) it skips over the first element in the list and (2) it returns String not found/found only after checking the first element:
def search_for_string(a_list, search_term): i=0 for search_term in a_list: i += 1 if a_list[i] == search_term: # whoops this comparison checks for succeeding elements! return 'string found!' elif a_list[i] != search_term: # whoops this part returns even before all succeeding elements are checked. return 'string not found2' if len(a_list) == 0: return 'string not found' apple = search_for_string(['a', 'b', 'c'], 'd') # In the list ['a', 'b', 'c'] # element [0] = 'a' # element [1] = 'b' # element [2] = 'c' print(apple)
To explain a little further let’s take this step by step through your code:
# search_term == 'd'
# a_list = [ 'a', 'b', 'c' ]
i = 0 # at this point i == 0
for search_term in a_list:
# Oh no! we lost the search term that we passed into the
# function because we are using it as the loop iterator
# search_term == 'a'
i += 1 # i == 1
if a_list[i] == search_term:
# checks to see if 'b' == 'a'
return 'string found!'
elif a_list[i] != search_term:
# checks to see if 'b' != 'a'
return 'string not found!'
# and we return after one iteration of the loop.
Your second version has the same problem (1)(2), but avoids the issue where the first element is not checked.
5 Comments
if needle == haystack --> if needle == x?search_term as your loop iterator. Also, since you are doing it at the top of your loop, you are skipping over checking element #0 if your intent was to compare the passed in search_term with a particular list element.There are lots of things wrong in your search_for_string function.
Main problem is that you're overwriting the value of the variable search_term. There are other problems as well that are causing incorrect output.
Here's a simpler version of your function and it meets all your requirements.
def search_for_string(a_list, search_item):
if(len(a_list) == 0):
return 'List is empty'
else:
for search_term in a_list:
if search_term == search_item:
return 'string found!'
return 'string not found'
Comments
You have quite a few errors in your in code. Some are important, others are not. I'll try to address them:
- You're receiving the variable
search_termas a function argument, but you then overwrite the value of it by using it in your for loop. - You're iterating over
a_listby value, but you then attempt to use the loop variableito iterate by index. Don't do this. You're already iterating by value, you don't need to do both. - You're trying to test if
a_listis empty at the end of your function. Do at the beginning. Better yet, ditch the if statement and simply return at the end of your function. The for loop will not be run ifa_listis empty.
Now, here is how I'd rewrite your function:
>>> def search_for_string(lst, key):
# only iterate by value.
for string in lst:
# we only need to test once
# if `key` is equal to the
# current string we are on.
if string == key:
return 'string found'
# no need to test if the list
# is empty. The for loop will
# never be run if it is, and
# this return statement will
# execute.
return 'string not found'
>>> search_for_string(['a', 'b', 'c'], 'd')
'string not found'
>>> search_for_string(['a', 'b', 'c'], 'b')
'string found'
>>> search_for_string([], 'b')
'string not found'
>>>
Comments
For your code, you should note that you're not searching properly. You pass in search_term, but a variable in a for x in y sets x to be equal to the value of the next item in y. So if you have for x in [1, 2, 3], the first time it runs it will set x = 1, etc. So first function will check if 'a' == 'b', which it's not, and the second function will check if 'a' == 'a', which it is--but neither is what you're looking for!
The best way to find if an item is in a list is
x in list
this will return True or False, if x is in the list or not! (don't use the variable 'list' though, it's bad practice since it shadows a built-in function).
So a more Pythonic way to do this would be
def search_for_string(a_list, search_term):
if search_term in a_list:
return 'string found!'
elif not a_list: # realistically you'd put this before here but I'm trying to mirror your code--why might you put this earlier? Because it's less costly than searching a list.
return 'empty list!'
else:
return 'string not found!'
Also note that bool([]) returns False, which is how we check if the list is empty.
To do it your way, we don't need to use index values, but you have to do a lot of extra, unnecessary work.
def search_for_string(a_list, search_term):
for index, item in enumerate(a_list):
if a_list[index] == search_term:
return 'string found!'
# what do you think the value of 'item' is here? it's equal to a_list[index]!
elif len(a_list) == 0: # again, you'd put this earlier--why make your computer do the work? it doesn't have to. Also, you could just do elif not a_list
return 'string not found'
else:
continue
return 'string not found2'
Comments
Most of the issues relevant to your code are covered in previous answers here, and the answer given by @Stephen Rauch sums up the most Pythonic approach to your problem.
There is one more thing that makes your code not do what you thing, even if all the other stuff was correct.
When you return in a function, you are effectively exiting that function.
So, effectively, using the for loop approach you've been trying, you would be only checking the first value in a_list, returning 'Found' if it met your search criteria, and returning 'Not found' if the first value did not match your search criteria, and then exiting your function.
Essentially, you'd never check beyond the first value.
Comments
First of all, difference in your first method and second method are incrementing i before and after your if statement is executed. If you increment i first, your loop won't find the value for the first element of the list. you are using i as an increment, but it is not necessary in python. You can just find out by using if the element is in a list.
def search_for_string(a_list, search_term):
#if a_list is empty, return False
if len(a_list) == 0:
return False
#if search_term has an element in a_list return the string
if search_term in a_list:
return "string found"
return "string not found"
print(search_term)as a line underneath the first line of your for loop.) This may help you debug.enumerate().It'd save you theiobject.