Python循环迭代问题

4

有两个版本,返回相反的答案,但总有一个是错误的。我不确定我哪里出了问题。我尝试了一系列其他选项,但这似乎是最接近的。编辑:需要在循环中

目标:识别列表中的元素,识别元素不在列表中时,识别列表为空时,根据情况返回字符串。

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)

其他测试:

apple = search_for_string(['a', 'b', 'c'], 'b')
apple = search_for_string([], 'b')

2
首先,您正在覆盖变量search_term的值。例如,您将其传递为“d”,但它将被覆盖,因为您的for循环使用相同的变量名称。要查看发生了什么,请尝试在for循环内部打印search_term的值(即在for循环的第一行下面添加print(search_term))。这可能会帮助您进行调试。 - Kevin Wang
我明白你的意思,但我不知道该怎么做哈哈。我会继续尝试。 - Megan
你可能想查一下 enumerate()。这样可以避免使用 i 对象。 - boardrider
谢谢!是的,我看过了(重新开始并找到解决该问题的方法呵呵)。它看起来确实会非常有用。 - Megan
哦,我不知道。我一定会再仔细检查的。谢谢你告诉我。 - Megan
显示剩余2条评论
8个回答

9

Python让这种事情变得非常容易:

def search_for_string(a_list, search_term):
    if search_term in a_list:
        return 'string found!'
    return 'string not found'

3

你的代码存在一些问题,不符合Python语言规范:

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'

根据您定义的目标,您可以这样实现:
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'))

输出:

String not found
First occurence of string Found at index position: 1
List is empty

2
简短回答是,!= 的返回值并不是你想象中的那样,而且列表是从0开始索引而不是从1开始。实际上,代码比你想象的要简单得多:
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!'

基本上,只有在检查了每个元素至少一次后,你才能知道字符串未被找到。但是,当你找到字符串时,你就知道它已被找到。
现在来解释一下你代码中的问题:
  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)
    
为了进一步解释,让我们逐步分析您的代码:
# 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.

你的第二个版本有相同的问题(1)(2),但避免了第一个元素未被选中的问题。


1
if needle == haystack 是否应改为 if needle == x - wwii
谢谢你发现了这个问题。 - 2ps
是的,这个可以。抱歉,我忘了提到我试图在循环内部做这件事。 - Megan
我的理解是将i=0设置为迭代从零开始,而i+=1则在每次循环中添加一个(因此移动元素到元素)。 - Megan
它确实可以,但由于您是在循环的顶部执行此操作,因此正如@mygz所指出的那样,您正在使用search_term作为循环迭代器来比较错误的内容。另外,由于您是在循环的顶部执行此操作,如果您的意图是将传入的search_term与特定列表元素进行比较,则会跳过检查元素#0的步骤。 - 2ps

1

大部分和你的代码相关的问题都在之前的回答中得到了解决,@Stephen Rauch提供的答案总结了解决你的问题最Pythonic的方法。

即使所有其他内容都正确,还有一件事会使你的代码不起作用。

当你在函数中使用return时,你实际上正在退出该函数。

因此,使用你一直尝试的for循环方法,你只会检查a_list中的第一个值,如果它符合你的搜索条件,则返回“Found”,如果第一个值不符合你的搜索条件,则返回“Not found”,然后退出你的函数。

基本上,你永远不会检查第一个值以外的值。


1

你的 search_for_string 函数有很多问题。

主要问题是你正在覆盖变量 search_term 的值。还有其他问题会导致输出不正确。

这里有一个更简单的版本的函数,它满足所有你的要求。

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'

1
您的代码中有很多错误,有些重要,有些不重要。我将尝试解决它们:
  • 您将变量search_term作为函数参数接收,但是您在使用for循环时覆盖了它的值。
  • 您正在按值迭代a_list,但是您尝试使用循环变量i按索引迭代。不要这样做。您已经按值进行迭代,不需要同时按索引迭代。
  • 您尝试在函数的末尾测试a_list是否为空。请在开头执行此操作。更好的方法是,放弃if语句,并在函数末尾简单地返回。如果a_list为空,则不会运行for循环。

现在,这是我如何重写您的函数:

>>> 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'
>>> 

1
对于你的代码,你需要注意你没有正确地进行搜索。你传递了search_term,但是在for x in y中,变量x被设置为y中下一个项目的值。因此,如果你有for x in [1, 2, 3],第一次运行它将设置x = 1,依此类推。所以第一个函数将检查'a' == 'b',但它不是,第二个函数将检查'a' == 'a',它是——但都不是你要找的!最好的查找列表中的项目的方法是:
x in list

这将返回True或False,表示x是否在列表中!(不要使用变量“list”,因为它会遮蔽内置函数,这是一种不好的实践。)
因此,更符合Python风格的方法是:
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!'

请注意,bool([])返回False,这是我们检查列表是否为空的方法。
按照你的方式,我们不需要使用索引值,但需要做很多额外且不必要的工作。
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'

1
首先,你的第一种方法和第二种方法的区别在于执行if语句之前和之后递增i。如果你先递增i,那么循环将无法找到列表的第一个元素的值。 你正在使用i作为递增量,但在Python中这是不必要的。你可以通过使用if语句来判断元素是否在列表中。
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"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接