简体   繁体   English

如何在Scheme中使用Car和Cdr打破(11(12 13))

[英]How to break (11 (12 13)) using Car and Cdr in Scheme

I need to return from a list only those values which are odd so I am trying to break my list using car and cdr functions. 我需要从列表中返回那些奇怪的值,所以我试图使用car和cdr函数打破我的列表。 I have a recursive funciton call that checks if the Car returns a list then further break it using car and cdr , otherwise just pass the first element to a function call check if Odd. 我有一个递归函数调用,检查Car是否返回一个列表然后使用car和cdr进一步打破它,否则只是将第一个元素传递给函数调用检查Odd。

The problem with the special case (10 11 (12 13)) is that car returns 10 cdr returns (11 (12 13)) 特殊情况(10 11(12 13))的问题是汽车返回10 cdr回报(11(12 13))

then in second iteration car returns (11 (12 13)) cdr returns (11 (12 13)) 然后在第二次迭代中汽车返回(11(12 13))cdr返回(11(12 13))

so How can i further break my list using car and cdr. 那我怎么能用汽车和cdr进一步打破我的清单。 I need to preserve the brackets in my final answer as well as only return the list having odd values of integers. 我需要在最终答案中保留括号,并且只返回具有奇数整数值的列表。

for a function that needs to work on an arbitrary nested list I find it easy to first write the flat list version (filter-odd in our case) and then edit it to produce the nested version (I will call it filter-odd*) 对于需要在任意嵌套列表上工作的函数,我发现很容易首先编写平面列表版本(在我们的例子中为filter-odd),然后编辑它以生成嵌套版本(我将其称为filter-odd *)

First for normal 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))])))

Now for filter-odd* (one right-hand side will be left as an exercise (though it seems like you know the answer from your question)) 现在为过滤器奇数*(一个右侧将作为练习留下(虽然你似乎知道你的问题的答案))

(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))])))

As a note, this design pattern can be used to help write any recursive program and convert it from only working on flat lists to working on arbitrarily deep lists. 需要注意的是,此设计模式可用于帮助编写任何递归程序,并将其从仅在平面列表上工作转换为在任意深度列表上工作。

Here's a general solution, for lists with an arbitrary level of nesting: 对于具有任意嵌套级别的列表,这是一个通用解决方案:

(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))))))

Notice that three cases need to be considered: 请注意,需要考虑三种情况:

  1. If the list is empty 如果列表为空
  2. If the first element of the list is not a list 如果列表的第一个元素不是列表
  3. If the first element of the list is a list 如果列表的第一个元素是列表

For the second case, two further cases need to be considered: 对于第二种情况,需要考虑另外两种情况:

  1. If the element is odd, then we add it to the list returned 如果元素是奇数,那么我们将它添加到返回的列表中
  2. If the element is even, we skip it and continue with the next element 如果元素是偶数,我们跳过它并继续下一个元素

Here's my take: 这是我的看法:

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

and then you can do: 然后你可以这样做:

> (filter* '(1 (2 . 3) ((4 . 5))) even?)
(2 4)
> (filter* '(1 (2 . 3) ((4 . 5))) odd?)
(1 3 5)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM