P01 (*) 获取列表最后一个元素【重补】
来源:互联网 发布:php 字符串匹配查找 编辑:程序博客网 时间:2024/06/02 16:52
今天在CSDN上丢了两篇文章,也促使我开始注意博客系统的使用方法。现在发现的问题有:
1. 草稿箱好像只能保存一篇文章,其他文章我怎么都保存不到草稿箱
2. 编辑文章不保存或不发表,文章莫名从文章列表里“丢失“
不知是产品缺陷,还是有意为之,我先把文章补上,这是其一。
进入问题之前,先说一说列表是什么,我们可以类比C/C++中的链表。按R7RS中所说,它可递归定义为:(1) 要么为空,即'()
,(2)要么是一个pair,其cdr
是列表。pair是一个二元对偶,跟std::pair
类似。可用标准函数list?
判断是否是一个有效列表。
以后的问题除特别说明,参数ls
都为有效列表。
进入问题:
Example:
sash> (my-last '(a b c d))sash> d
这是原先我给出的三种解决方案:
(1)自己造轮子
Scheme内置的列表本质上是单链表,要查找最后一个元素,只能依次遍历列表,找到其cdr
为'()
的列表,并返回其car
。如
(define my-last (lambda (ls) (if (null? ls) (raise 'not-found) (let ([t (cdr ls)]) (if (null? t) (car ls) (my-last t))))))
如果列表为空,应返回一个值表示失败。但列表中的值是任意的,不好确定合适的值,这里用raise
抛出异常。
(2)使用list-ref
和length
列表的长度等于元素的个数,而list-ref
索引从0开始,结合起来:
(define my-last (lambda (ls) (let ([len (length ls)]) (if (zero? len) (raise 'not-found) (list-ref ls (- len 1))))))
(3)使用reverse
可以先反向排列列表,这样所得列表的第一个元素即为所求。
(define my-last (lambda (ls) (if (null? ls) (raise 'not-found) (car (reverse ls)))))
更新
在回顾的时候,发现方法(1)有逻辑冗余。这里在关键语句加上数字标签,帮助我们分析。
(define my-last (lambda (ls) (if (null? ls) (1) (raise 'not-found) (let ([t (cdr ls)]) (if (null? t) (2) (car ls) (my-last t)))))) (3)
看以下(my-last '(1 2))
这个调用的语句执行顺序,会得到
执行序列(1)–>(2)–>(3)->(1)–>(2)。(3)前后都是判断列表是否为空,(2)判断了列表t
,在新的递归中,t
替换了ls
,(1)判断了ls
,实际上同一个列表t
被判断了两次。
避免冗余,代码修改如下:
(define my-last (lambda (ls) (if (null? ls) (raise 'not-found) (let loop ([h (car ls)] [t (cdr ls)]) (if (null? t) h (loop (car t) (cdr t)))))))
出现之前的原因在于,混淆前提和主体。第一个null?
判断在于给整个递归提供一个健康的环境,下面的递归主体其实就是循环不变式:若cdr
为空,返回car
。
- P01 (*) 获取列表最后一个元素【重补】
- P04(*) 获取列表的长度【重补】
- JavaScript 获取数组的最后一个元素
- php 获取数组第一个元素 以及最后一个元素 && 最后一个元素的键名
- Scala练习题01:找出列表中最后一个元素
- PHP判断最后一个元素及获取key
- 如何利用迭代器获取vector的最后一个元素
- jquery如何获取第一个或最后一个子元素?
- 获取数组最后一个元素的key值
- jquery如何获取第一个或最后一个子元素?
- 使用mongodb的aggregate实现获取数组最后一个元素
- firstChild,lastChild 获取第一个/最后一个元素节点
- js点击列表的第一个元素,不起作用,最后一个元素起作用
- p01
- python列表元素去重
- 对列表元素去重
- vector容器的end是指向最后一个元素的下一个位置,使用时要将迭代器减1,才能获取到最后一个
- 删除数组最后一个元素
- [].slice
- Dynamics CRM2015 on-premises直接升级Dynamics CRM2016 on-premises
- MongoDB学习第一弹
- 双曲型偏微分(谱方法)
- Linux中安装nginx
- P01 (*) 获取列表最后一个元素【重补】
- Android Studio——android中的文件操作详解以及内部存储和外部存储
- 月入30K的程序员要避开哪些坑?
- 椭圆型差分
- Tomcat去除项目名称和端口号,直接使用ip地址访问项目的方法
- Android PullToRefresh 源码分析
- Android 应用程序无响应(ANR)报错原因
- [Coursera]算法基础_Week9_考试_Q3
- Trees Made to Order