If statement Racket新手:为什么if语句会影响回报?
我刚开始学习球拍,所以我仍在努力弄清楚这门语言的复杂性。我正在尝试在列表中实现自己的搜索功能。如果函数找到它,则返回索引,否则返回-1If statement Racket新手:为什么if语句会影响回报?,if-statement,scheme,racket,If Statement,Scheme,Racket,我刚开始学习球拍,所以我仍在努力弄清楚这门语言的复杂性。我正在尝试在列表中实现自己的搜索功能。如果函数找到它,则返回索引,否则返回-1 (define (find-index list item) (if (equal? (length list) 1) (if (equal? (first list) item) 0 1) (if (equal? (first list) item) 0 (+ 1 (my-search (re
(define (find-index list item)
(if (equal? (length list) 1)
(if (equal? (first list) item) 0 1)
(if (equal? (first list) item)
0
(+ 1 (my-search (rest list) item)))))
所以find index函数是一个递归函数,它遍历列表,寻找一个等价于“item”的项。我编写它是为了,如果列表中有4个元素,该函数可以返回0-4之间的任何数字
(define (my-search list item)
(define length (my-length list))
(define index (find-index list item))
(if (= index length) -1 index))
我的想法是,如果find index函数返回一个等于列表长度的数字,这意味着该函数没有找到该项,因此我的搜索函数应该返回-1
然而,当我投入
(my-search (list "apple" "barbecue" "child" "demon" "enter") "fire")
我得到的结果是3,而不是-1。如果在If语句之前打印索引,则索引是3而不是5。如果
(if (= index length) -1 index))
不是我搜索功能的一部分,那个么一切都很好
我认为索引是函数本身的id,而不是函数的结果。但是,我不明白为什么这会影响我搜索的返回结果。有人愿意就这个问题解释一下吗
此外,欢迎任何风格批评。我想知道我是否没有遵循惯例。这种奇怪的行为是由
find index
正在调用my search
而调用find index
(一种相互递归!)这一事实造成的。在某种程度上,额外的if
会导致递归过早结束。解决方案:在find index
过程中将对my search
的调用替换为find index
既然已经解决了这个问题,我们可以编写一个过程来在列表中查找元素的索引,或者发出未找到元素的信号,如下所示:
(define (find-index lst item)
(cond ((empty? lst) #f)
((equal? (first lst) item) 0)
(else
(let ((result (find-index (rest lst) item)))
(if result (add1 result) #f)))))
让我们看看上面的内容如何改进您的程序:
- 构造具有多个条件的程序的首选方法是使用
cond
- 不应将
用作参数名称,它与同名的内置过程冲突列表
- 出于同样的原因,您不应该调用
本地定义length
- 使用
检查是否超出了列表不是一个好主意,一个构建良好的递归将解决这个问题,而无需再次迭代列表length
- 通常使用
表示搜索过程没有找到它要查找的内容#f
- 在结构良好的列表递归中,您应该检查列表是否为空,通常这是我们编写的第一个基本情况-如果传递了空列表,您的过程将失败
- 我们使用
来声明局部变量,在这种情况下,避免调用递归两次是有意义的let
- 使用
,它比(add1 x)
(+1 x)
let
:
(define (find-index lst item)
(let loop ((lst lst) (idx 0))
(cond ((empty? lst) #f)
((equal? (first lst) item) idx)
(else (loop (rest lst) (add1 idx))))))
您可以验证这两个过程是否按照广告的方式工作:
(find-index (list "apple" "barbecue" "child" "demon" "enter") "fire")
=> #f
(find-index (list "apple" "barbecue" "child" "demon" "enter") "child")
=> 2
这就是我解决问题的方法
(define (find-index L item) ; L your list. item the item for which you want the index
(define (aux L res) ; Auxiliary function. L your list. item the item for which you want the index
(cond ((null? L) -1) ; No thing was found, return -1.
((eq? (car L) item) res) ; If the item is equal to the current item then return the position.
(else (aux (cdr L) (add1 res))))) ; Move on to the next item in the list and increment the position.
(aux L 0)) ; Call of the auxiliary function that will be doing the job
试运行
(define L '(a b c d))
元素不在列表中
(find-index L 'e)
输出:-1
元素“d”
输出:3这里是一个版本的
查找索引
,它尝试使用与原始示例相同的样式。我使用的不是list
,而是xs
(它是“x的列表”的缩写)
请注意,最好使用假值#f
表示“未找到”
这是一个非常有用的回答。我很感激帮助我改进代码的要点。我还学到了尾部递归是正确的方法。但是,它仍然不能回答我的问题,为什么if语句会影响索引的结果,甚至在if语句之前。如果我删除if语句和println索引,索引是5(假设列表中找不到该项)。当if语句存在时,println索引变为3。不,递归结构正确。如果在列表中找不到该项,如果我的搜索函数的最后一条if语句不在列表中,我将得到5。
(定义(我的搜索列表项)(定义长度(我的长度列表))(查找索引列表项))
如果找不到该项,将返回我5,并显示大小列表4@VivienK我发现了窃听器。是的,您的递归肯定是不正确的:find index
正在调用my search
,它正在调用find index
(一个相互递归!)。在某种程度上,额外的if
会导致递归过早结束。解决方案:在查找索引
过程中将对我的搜索
的调用替换为查找索引
。哦,我的上帝,谢谢你。我觉得自己像个疯子。感谢您花时间调试我的代码。
(find-index L 'd)
(define (find-index xs item)
(if (empty? xs)
-1 ; not found
(if (equal? (first xs) item)
0 ; found at beginning
(let ([index-in-rest (find-index (rest xs) item)]) ; index in rest of list
(if (= index-in-rest -1)
-1 ; not found in rest of list
(+ 1 index-in-rest)))))) ; add 1 because we skipped
the first element