3

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')
7
  • 2
    first of all, you're overwriting the value of the variable search_term. You're passing it in as 'd', for example, but it'll be overwritten because your for loop uses the same variable name. To see what's happening, try printing the value of search_term inside the for loop. (i.e. add print(search_term) as a line underneath the first line of your for loop.) This may help you debug. Commented Jan 8, 2017 at 5:40
  • I see what you mean, but I don't know what to do about it haha I'll keep messing around Commented Jan 8, 2017 at 5:47
  • You may want to look up enumerate(). It'd save you the i object. Commented Jan 8, 2017 at 20:56
  • Thank you! Yeah, I've checked it out (post starting over and finding a solution for this problem haha). It does look like it would be super helpful. Commented Jan 9, 2017 at 1:21
  • Can you please go back through all your posts and both select answers where appropriate and upvote the answer you picked and any others you consider worthwhile, albeit not the answer you ultimately chose. I don't mean to sound rude, so apologies if it comes across that way, but it's an incredibly important part the how Stack Exhange and its network operates (disclaimer - I gave a selected answer and didn't get my expected upvote on top of that, so I may be a little biased and grumpy... ;) ). Stephan Rauch gave an excellent answer below. Commented Jan 18, 2017 at 0:41

8 Answers 8

9

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'
Sign up to request clarification or add additional context in comments.

Comments

3

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

2

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:

  1. 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?
Thank you for catching that.
Yes, this works. Sorry Forgot to mention trying to do this inside a loop.
my understanding was setting i=0 starts the iteration at zero, and i+=1 adds one every time it loops through (hence moving element to element)
It does, but since you are doing it at the top of your loop, you are, as pointed out by @mygz comparing the wrong things since you are using 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.
1

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

1

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_term as a function argument, but you then overwrite the value of it by using it in your for loop.
  • You're iterating over a_list by value, but you then attempt to use the loop variable i to 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_list is 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 if a_list is 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

1

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

1

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

1

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"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.