获取列表中最后一个元素的方案

时间:2017-11-02 20:11:51

标签: list recursion scheme cdr

我对计划和汽车,cdr等的想法很新。我有这个函数来返回列表的最后一个元素,但是现在它只返回一个空列表。

 (define (last mylist)
      (if (list? mylist)
              (if (null? mylist)
                  (if (null? (cdr mylist))
                      '()
                      (last (cdr mylist)) 
                   )
              )        
      )
)

5 个答案:

答案 0 :(得分:2)

本书How To Design Programs通过为您提供具体而详细的设计方案,帮助您解决这个问题。第9.2节“非空列表”中介绍了这个特殊问题。从广义上讲,以下是您需要遵循的步骤:

  • 为非空列表制定数据定义(或从书中获取)
  • 为函数编写目的语句,签名和标题
  • 写测试案例(您的测试用例将在此处帮助批次。(请记住,您不需要测试数据定义不允许的输入)
  • 添加与您的数据定义相关联的模板(也出现在书中)
  • 填写模板中的空白处以完成您的定义
  • 调试。

答案 1 :(得分:2)

仅凭你的缩进,很明显你是从另一种编程语言来到Scheme

但您也错误地使用if - 在Scheme中,您不能拥有单分支 if语句。嗯,在Scheme中根本没有语句,只有表达式,而if表达式总是需要3个操作数(参数)

  1. 谓词(条件)
  2. 结果(如果谓词为真,会发生什么)
  3. 替代(当谓词为false时会发生什么)
  4. 你的节目很接近。只需稍加调整就可以了解您需要的位置 - 请注意缩进如何让您轻松查看if的3个操作数。

    (define (last mylist)
      (if (null? mylist)
          #f
          (if (null? (cdr mylist))
              (car mylist)
              (last (cdr mylist)))))
    

    最后,Scheme提供cond,有助于防止条件序列不必要的代码嵌套

    (define (last mylist)
      (cond ((null? mylist)
             #f)
            ((null? (cdr mylist))
             (car mylist))
            (else
             (last (cdr mylist)))))
    
    (last '())
    ;; #f
    
    (last '(1))
    ;; 1
    
    (last '(1 2))
    ;; 2
    
    (last '(1 2 3))
    ;; 3
    

    超出这个答案的范围是#f的返回值(last '()) - 我认为在空列表上调用last应该具有调用{{1}的相同效果在一个空列表上。但是我会把它留给你。

答案 2 :(得分:1)

如果(null? mylist)不成立,那是什么?非空列表。

非空列表可能包含一个或多个元素。

有多少元素有这样的列表,它们的最后一个元素是它们的第一个?

关于此类列表可以说什么? cdr?您应该使用它来提前停止递归。现在它一直持续到列表为空,但你需要提前停止。

(define (last mylist)
      (if (list? mylist)
              (if (null? mylist)
                  '()
                  ;; {1}
                  (last (cdr mylist))
                  ;;
                  )))

{1},您无条件致电(last (cdr mylist))。但是,如果你已经到达列表的末尾怎么办?如果只剩下一个元素怎么办?在这种情况下,您需要返回 it 作为结果。因此,用if表达式替换无条件代码来完成此任务。

答案 3 :(得分:1)

当您提出问题(null? (cdr mylist))时,如果该问题是真的而不是(car mylist),则应该返回'()。从那时起,它意味着mylist是单原子列表。

(define (last mylist)
  (cond ((null? mylist) '())
        ((null? (cdr mylist)) (car mylist))
        (else (last (cdr mylist)))))

您可以使用cond代替if来避免嵌套条件,因为cond处理多个手臂,而if通常用于当您只有两个选项时条件。

这本书the Little Schemer最能帮助我想象一下Scheme计划中发生了什么。

答案 4 :(得分:0)

我认为这最接近您的初始代码:

(define (last mylist)
  (if (list? mylist)
      (if (null? mylist)
          '() ; input list is empty
          (if (null? (cdr mylist))
              (car mylist) ; list only has one remaining element so this is it
              (last (cdr mylist)))) ; otherwise, recurse
      #f)) ; input is not a list

使用if时,请务必同时填写 true false 分支。