在LispWorks中进行编程14:处理列表中的项目
Category:UI界面编写处理列表中的项目
在本课中,我们将展示如何对列表中的每个项目执行相同的操作集。
查找数字列表的总和
让我们看一下编写程序总和列表来查找数字列表总和的问题。我们希望能够像这样调用它:
CL-USER > (sum-list ‘(2 3 5 7 11 13 17 19))77
在Lisp中解决问题的诀窍是将其分解为更简单的问题。我们可以用英语编写解决方案如下:
要查找数字列表的总和:
- 如果列表为空,则答案为0
- 否则,答案是添加到剩余数字的总和列表中的第一个数字。
乍一看,我们还没有解决问题,因为我们仍然需要找到“剩余数字的总和”。但这是一个比我们开始的更短的列表,并且在程序的许多应用程序之后,这将是一个空列表,我们知道如何解决。
我们在Lisp中编写它的方式与英文描述非常相似:
(defun sum-list (numbers) (if (null numbers) 0 (+ (first numbers) (sum-list (rest numbers)))))
我们编写了一个程序,可以找到无限数量的总和。我们可以给它一个百万数字的列表,它将按预期工作!
递归
过程 sum-list 通过在其定义中包括对其自身的调用来重复对项目列表的操作。这称为 递归。它不会导致无限循环,因为您可能最初期望,因为测试 (if(空数)… 结束递归。
在大多数其他计算机语言中,实现sum-list的自然方式是使用迭代构造,例如 for … next 或 do … until。在Lisp中,递归通常提供更简洁,更直观的方法来解决这样的问题。
将列表中的每个数字加倍
创建一个与原始列表相同但每个数字加倍的新列表的问题怎么办?我们希望这项工作如下:
CL-USER > (double-list ‘(2 3 5 7 11 13 17 19))(4 6 10 14 22 26 34 38)
英文解决方案如下:
要将数字列表加倍:
- 如果列表为空,则答案为零
- 否则,答案是从第一个数字的两倍构建的列表,然后是剩余数字列表的两倍。
Lisp中的过程如下:
(defun double-list (numbers) (if (null numbers) nil (cons (* 2 (first numbers)) (double-list (rest numbers)))))
它与sum-list的定义非常相似,只是我们使用cons来构造一个新列表并将其作为答案返回。
过程sum-list和double-list是解决涉及使用列表的一系列问题的有用原型。
- sum-list对列表的每个元素进行操作并返回单个结果。
- double-list对列表的每个元素进行操作,并返回一个新的转换列表。
在后面的课程中,我们将看到如何将这两个过程推广到我们可以用于各种应用程序的通用工具中。
为列表中的每个元素做一些事情:dolist
最后,我应该提一个内置的Lisp构造,dolist,它通常提供了一种方便的方法来对列表中的每个元素执行一系列操作。
它是这样写的:
(dolist (item list) body)
哪里:
- list 是元素列表。
- item 依次设置为列表的每个元素。
- body 是为每个item值执行的一个或多个Lisp过程。
例如:
(dolist (i ‘(2 3 5 7 11)) (print (* i 2)))
将打印:
46101422
演习
在以下练习中,根据需要调整sum-list或double-list以解决问题:
1.计算列表中的元素数量
编写一个过程count-list来计算列表中元素的数量。所以:
(count-list ‘(2 3 5 7 11 13 17 19)
应该返回8。
2.反转字符串列表中的每个字符串
编写一个程序反向列表来反转单词列表中的每个单词。例如:
(reverse-list ‘(“dog” “pan” “tar” “tip” “net”))
应该返回:
(“god” “nap” “rat” “pit” “ten”)
3.查找列表中的每个数字是偶数还是奇数
编写一个程序evenp-list来处理一个数字列表,如果它是偶数则用t替换每个数字,如果它是奇数则用nil替换。所以:
(evenp-list ‘(1 2 3 4 5 6 7 8))
应该返回:
(nil t nil t nil t nil t)
4.找到列表的最大元素
编写一个过程max-list来返回列表的最大元素。所以:
(max-list ‘(11 13 17 19 2 3 5 7))
应该返回19。
5.复制列表中的每个元素
编写一个程序dupli-list来复制列表的元素。例如:
(dupli ‘(a b c c d))
应该给:
(A A B B C C C C D D)
6.消除列表中的连续重复项
编写一个过程压缩,用一个元素副本替换重复的元素。不应更改元素的顺序。
(compress ‘(a a a a b c c a a d e e e e))
应该给:
(A B C A D E)
7.交错两个列表
编写一个将交错两个列表的过程交错。你可以假设它们的长度相同。例如:
(interleave ‘(a b c) ‘(d e f))
应该给;
(A D B E C F)
8.在关联列表中查找条目
关联列表是一种将数据存储为条目列表的方法。每个条目都是一个列表,其中第一个项目是唯一键; 例如:
(defparameter *type* ‘((cat mammal) (dog mammal) (lizard reptile) (salmon fish)))
编写一个带有键和关联列表的过程查找,并返回与该键匹配的条目。例如:
(lookup ‘cat *type*)
应该给:
(cat mammal)
如果未找到密钥,则查找应返回nil。
http://mip.i3geek.com