Python 递归线性搜索-返回列表索引
我有一个函数search,它在一个列表('l')中搜索键,如果找到,则返回True,否则返回False。如果找到,我希望它返回key的索引,如果没有找到,则返回False,但我不知道返回语句应该是什么。这是我的密码:Python 递归线性搜索-返回列表索引,python,recursion,Python,Recursion,我有一个函数search,它在一个列表('l')中搜索键,如果找到,则返回True,否则返回False。如果找到,我希望它返回key的索引,如果没有找到,则返回False,但我不知道返回语句应该是什么。这是我的密码: def search(l,key): """ locates key in list l. if present, returns location as an index; else returns False. PRE: l is a lis
def search(l,key):
"""
locates key in list l. if present, returns location as an index;
else returns False.
PRE: l is a list.
POST: l is unchanged; returns i such that l[i] == key; False otherwise.
"""
if l: # checks if list exists
if l[0] == key: # base case - first index is key
return True
s = search(l[1:], key) # recursion
if s is not False:
return s
return False # returns false if key not found
非常感谢您的帮助。对于您的基本案例,您刚刚在索引0处找到了该项目,对吗?返回0
if l[0] == key: # base case - first index is key
return 0
对于递归部分,让我们考虑返回什么。假设该项位于索引5处。因为我们已经给递归调用传递了一个移位一个元素的列表,它将找到它并返回4。(4,不是5。你明白为什么吗?)
在返回索引之前,我们需要添加一个以取消移动索引
s = search(l[1:], key) # recursion
if s is not False:
return s + 1
问题是,您正在对列表的尾部进行切片,而没有保留有关切片发生位置的任何信息 事实上,您根本不需要对列表进行切片,因为您可以在列表中执行索引查找 线性搜索的算法是原始递归的,因此如果你能找到一个迭代的解决方案,递归的解决方案是很容易达到的(反之亦然) 因此,迭代解决方案可能如下所示:
for every integer i between zero and length of list
if the element at position i in the list is equal to the key
return i
else
return "I couldn't find it"
我们将迭代解转换为递归解基本上意味着将循环转换为函数调用,其参数是下一个循环迭代的值。循环变量是
i
和正在搜索的列表。为了让你能从练习中学习,我就到此为止。你需要跟踪索引。因为您的最终返回值[如果发生真正的搜索]是布尔值,所以您必须更改它。我想下面的代码应该会对您有所帮助,但一定要彻底测试它,因为我只是试图理解意图,并没有彻底测试逻辑-
def search(l,key,idx=0):
"""
locates key in list l. if present, returns location as an index;
else returns False.
PRE: l is a list.
POST: l is unchanged; returns i such that l[i] == key; False otherwise.
"""
if l: # checks if list exists
if l[0] == key: # base case - first index is key
return idx
s = search(l[1:], key, (idx + 1)) # recursion
if s is not False:
return s
return False # returns false if key not found
您的API设计存在严重缺陷
>>> False == 0
True
你的导师正在给你设置惊喜。例如:
where = search(["non-foo", "not-foo"], "foo") # returns False
if where == 0:
print "foo is in pole position"
# but "foo" isn't even a candidate
使其在出现故障时返回None
。试试这个:
>>> def search(alist, key, pos=None):
... if pos is None: pos = len(alist) - 1
... if pos < 0: return None
... if key == alist[pos]: return pos
... return search(alist, key, pos - 1)
...
>>> search([1,2,3], 4) # -> None
>>> search([1,2,3], 3)
2
>>> search([1,2,3], 2)
1
>>> search([1,2,3], 1)
0
>>> search([], 1) # -> None
>>>
应该注意,我不能使用内置的.index函数或in运算符。我想如果没有这些,我已经很接近了。没有看到这个评论,你不能使用索引。但方法也可以类似。请尝试并在此处发布您的答案。请确保您的讲师知道(a)当这一问题出现在足够长的列表中时,您仍然可以通过(b)以递归为主的课程最好用支持递归的语言教授。如果所说的教练试图让你使用二传手或接球手,给他/她一个坚定但不具毁灭性的耳光,并告诉他们这是来自aaronasterling的。@aaronasterling:+1我猜,这更像是一个介绍性练习,限制他们使用python中提供的工具,并提出尊重这些约束的解决方案。当然,他们还应该告诉他们,为什么这个解决方案不适合/不如Python中的其他解决方案。在我发布我的答案之后,我看到了他的评论,并且得到了反对票。这不是Python!使用
for
循环迭代列表,不使用递归。+1是一个很好的解释,无需做家庭作业。我认为在失败的情况下返回None
比返回False
更好(函数从不返回True
),但这可能是一个品味问题。-1感谢您在没有解释它是由极其丑陋的API设计所必需的情况下,获得了极其丑陋的if is not False
。谢谢John,我理解你为什么要添加一个。这个解决方案(没有参数“idx”)更合适吗?或者反之亦然?@JMJY:inspectorG4dget在胡说八道:-(@JohnMachin:我现在已经看到了你的解决方案,并且对它们+1。我不相信我在发布此评论时看到了你的答案。回头看看时间戳。似乎你可能在我发布我的评论后不久就发布了你的答案。@inspectorG4dget:No“似乎”。我的评论确实是在我发布我的答案之前发表的,在那些情况下是非常有效的……您没有对您正在推动的代码进行严格检查,认为它是“正确的解决方案”@JohnMachin:我似乎有一个错误的印象。我的道歉谢约翰,谢谢你的帮助。我只是想知道你的xsearch、ysearch和zsearch之间的区别是什么?你只是在压缩代码吗?@JMJY:我在重构anirvan的代码(xsearch)以删除不必要的代码,这会造成不好的结果“if s not False”消失。请注意我在过程中添加到代码中的注释;我将返回并用“######”突出显示它们。如果“just”是指“仅仅”,请重新思考——臃肿的代码是糟糕的代码。感谢您的帮助和澄清。
def xsearch(l,key,idx=0):
if l: # checks if list exists
if l[0] == key: # base case - first index is key
return idx
s = xsearch(l[1:], key, (idx + 1)) # recursion
if s is not False:
return s
#### and if s is False, it falls through and returns False ####
#### so it can return s unconditionally! ####
return False # returns false if key not found
def ysearch(l,key,idx=0):
if l: # checks if list exists
if l[0] == key: # base case - first index is key
return idx
return ysearch(l[1:], key, (idx + 1)) # recursion
return False # returns false if key not found
#### above statement is better put closer to the `if` ####
def zsearch(l,key,idx=0):
if not l: # checks if list exists
return False
if l[0] == key: # base case - first index is key
return idx
return zsearch(l[1:], key, (idx + 1)) # recursion