方案循环不会遍历列表中的所有元素
Posted
技术标签:
【中文标题】方案循环不会遍历列表中的所有元素【英文标题】:scheme loop does not iterate through all elements in the list 【发布时间】:2020-11-16 16:20:40 【问题描述】:我正在尝试根据条件更改列表中的元素。假设我有一个清单, L = '(0 1 1 0 0)。我只希望在此列表中找到的第一个“零”为“零”,对于该列表中的任何其他“零”,我希望它们为 1。因此我的示例列表将变为 L = '(0 1 1 1 1)。这是我到目前为止所做的,
(let dLoop ((L '(0 1 1 0 0))
(i 0)
(j 1))
(if (and (<= i (length L)) (<= j (- (length L) 1)))
(begin
(if (zero? (list-ref L i))
(begin
(cond
[(zero? (list-ref L j)) (list-set L j 1)]
[else (dLoop L i (add1 j))]
)
)
(dLoop L (add1 i) (add1 j))))
L))
这只会返回,L = '(0 1 1 1 0)
由于某种原因,一旦找到第一个重复的零,代码就会终止!我真的很感激有关此问题的一些见解
【问题讨论】:
也许你可以使用cdr
和cons
,而不是像在C中那样迭代循环;一种更常见于 lisps 的方法。
【参考方案1】:
在您的 (cond) 表达式中,如果 (zero? (list-ref L j)) case 求值,则您没有对 dLoop 的递归调用。这会导致 (cond) 返回,然后 (begin) 返回并最终退出 you (let) 表达式。然而,除了 Lazer 所说的,这有点不是标准的方案方法,更不用说非常有效了,因为链表上的 (list-ref) 每次都是 O(n)。也许尝试类似:
(define (find-and-map-rest lst pred f)
(cond [(null? lst) lst]
;; found the thing
[(pred (car lst)) (cons (car lst)
(map f (cdr lst)))]
;; didn't find the thing... yet
[else (cons (car lst)
(find-and-map-rest (cdr lst)
pred f))]))
(define (zero->one x)
(if (zero? x) 1 x))
(find-and-map-rest '(0 1 1 0 0) zero? zero->one)
【讨论】:
【参考方案2】:对于这样的任务,现实的代码可能无法完成cons
ing 的所有工作。代码真正需要做的就是找到第一个零,取列表的第一部分直到并包括该零,然后将其附加到与输入列表的其余部分一样长的一列中。如果没有找到零,则结果只是输入列表:
(define (f xs)
(let ((rest (member 0 xs)))
(if rest
(let ((ones-count (sub1 (length rest))))
(append (take xs (- (length xs) ones-count))
(make-list ones-count 1)))
xs)))
示例交互:
scratch.rkt> (f '(0))
'(0)
scratch.rkt> (f '(1))
'(1)
scratch.rkt> (f '(0 1 1 0 0))
'(0 1 1 1 1)
scratch.rkt> (f '(1 1 0 1 1 1 0 0 1 0 1 0))
'(1 1 0 1 1 1 1 1 1 1 1 1)
【讨论】:
以上是关于方案循环不会遍历列表中的所有元素的主要内容,如果未能解决你的问题,请参考以下文章
为啥带有pop-method(或del语句)的for循环不会遍历所有列表元素