3

我只需要从列表中返回那些奇数的值,所以我试图使用 car 和 cdr 函数来打破我的列表。我有一个递归函数调用,它检查 Car 是否返回一个列表,然后使用 car 和 cdr 进一步打破它,否则只需将第一个元素传递给函数调用,检查是否为奇数。

特殊情况 (10 11 (12 13)) 的问题是 car 返回 10 cdr 返回 (11 (12 13))

然后在第二次迭代中 car 返回 (11 (12 13)) cdr 返回 (11 (12 13))

所以我怎样才能使用 car 和 cdr 进一步打破我的清单。我需要在最终答案中保留括号,并且只返回具有奇数整数值的列表。

4

3 回答 3

4

对于需要在任意嵌套列表上工作的函数,我发现很容易首先编写平面列表版本(在我们的例子中为 filter-odd),然后对其进行编辑以生成嵌套版本(我将其称为 filter-odd*)

首先是普通过滤器 - 奇数

(define filter-odd
   (lambda (ls)
      (cond
        [(null? ls) '()]
        [(odd? (car ls)) (cons (car ls) (filter-odd (cdr ls)))]
        [else (filter-odd (cdr ls))])))

现在对于 filter-odd* (右侧将留作练习(尽管您似乎知道问题的答案))

(define filter-odd*
   (lambda (ls)
      (cond
        [(null? ls) '()]
        [(list? (car ls)) #| Do something with both car and cdr of ls |# ]
        [(odd? (car ls)) (cons (car ls) (filter-odd* (cdr ls)))]
        [else (filter-odd* (cdr ls))])))

需要注意的是,这种设计模式可用于帮助编写任何递归程序,并将其从仅处理平面列表转换为处理任意深度的列表。

于 2012-04-12T14:13:59.507 回答
1

对于具有任意嵌套级别的列表,这是一个通用解决方案:

(define (odds-list lst)
  (cond ((null? lst) '())                 ; the list is empty
        ((not (list? (car lst)))          ; first element is not a list
         (if (odd? (car lst))             ; element is odd
             (cons (car lst) (odds-list (cdr lst))) ; build the returned list
             (odds-list (cdr lst))))      ; element is even
        (else (cons (odds-list (car lst)) ; first element is a list
                    (odds-list (cdr lst))))))

请注意,需要考虑三种情况:

  1. 如果列表为空
  2. 如果列表的第一个元素不是列表
  3. 如果列表的第一个元素是列表

对于第二种情况,需要考虑另外两种情况:

  1. 如果元素是奇数,那么我们将它添加到返回的列表中
  2. 如果元素是偶数,我们跳过它并继续下一个元素
于 2012-04-12T15:15:41.427 回答
0

这是我的看法:

(define filter*
  (lambda (e f)
    (cond ((pair? e)
           (append (filter* (car e) f)
                   (filter* (cdr e) f)))
          ((null? e) '())
          ((f e) (list e))
          (else '()))))

然后你可以这样做:

> (filter* '(1 (2 . 3) ((4 . 5))) even?)
(2 4)
> (filter* '(1 (2 . 3) ((4 . 5))) odd?)
(1 3 5)
于 2015-01-27T10:18:36.677 回答