Scheme循环遍历包含列表

时间:2017-12-26 14:43:51

标签: scheme

我在Scheme中做了一个问题,就是创建一个函数,它接受一个对象和一个表达式,例如(foo 'x '(x 10 x x 4)),并且必须返回跟随给定对象的所有对象,所以上面的函数调用会返回(10 x 4)。但是,该表达式还可以包含列表,例如(foo 'y '(y (3 y 5 y y 8 9) (10 y 12 13 y 15 y) 17))应返回((3 y 5 y y 8 9) 5 y 8 12 15)。当它们包含列表时我遇到了麻烦。到目前为止,这是我的代码。

(define (foo target expression)
  (cond [(null? expression)]
        [(list? (first expression)) (foo target (first expression))]
        [(eqv? (first expression) target) (cons (first (rest expression)) (foo target (rest expression)))]
        [(not (eqv? (first expression) target)) (foo target (rest expression))]))

因此,当表达式包含列表时,我试图以递归方式调用该列表上的函数,但是,我不知道如何返回原始表达式继续搜索。

所以,当我打电话给(foo 'y '(y (3 y 5 y y 8 9) (10 y 12 13 y 15 y) 17))时,我得到了((3 y 5 y y 8 9) 5 y 8 . #t),所以它成功地遍历第一个列表,但是在此之后它停止并且没有到达表达式中的第二个列表

另外,我遇​​到的另一个问题是我的结果中的布尔值,我知道这是因为行cond [(null? expression)],我添加了这个,因为当它到达结束时我收到了一个错误表达式,我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

请注意,(cons x (cons y ...只有在使用空列表'()终止时才会成为正确的列表。因此(cons x (cons y ... empty))是正确的,相当于(list x y ...),而不是你拥有的(cons x (cons y ... #t))'()。您可以通过将(first (rest expression))作为基本案例的结果来解决此问题。

但是你还需要第二个基本案例来测试输入列表何时少于2个元素。这是因为您的函数稍后尝试以expression的形式访问第二个元素。因此,为了确保这是有效的,您需要确保... (null? (rest expression)) ...至少包含2个元素。这可以在您的cond案例中以[(list? (first expression)) (foo target (first expression))] 完成。

另一方面,你的函数只迭代它遇到的第一个列表元素,因为这行:

(first expression)

在这种情况下,您只需处理(first expression),但您需要同时处理(rest expression)(cons (foo target (first expression)) (foo target (rest expression))) 。由于您正在重建列表,因此可以使用cons as:

append

但这会重新创建原始列表的深度。从您想要的输出示例中,您似乎想要展平结果,因此更好的选择是(append (foo target (first expression)) (foo target (rest expression))) 将它们作为:

(define (foo obj expr)
  (cond
    [(null? expr) #f]
    [(null? (rest expr)) '()]
    [(pair? (first expr))
     (append (foo obj (first expr))
             (foo obj (rest expr)))]
    [(equal? obj (first expr))
     (cons (second expr)
           (foo obj (rest expr)))]
    [else
     (foo obj (rest expr))]))

考虑以下重写:

(foo 'x '(x 10 x x 4))
=> '(10 x 4)
(foo 'y '(y (3 y 5 y y 8 9) (10 y 12 13 y 15 y) 17))
=> '((3 y 5 y y 8 9) 5 y 8 12 15)

然后你会:

(foo 'x '())
=> #f
(foo 'x '(x))
=> '()

但你也会:

{{1}}