我有一个这样的列表:
(4 5 6 3 12 22 4 4 55 43 1 4 0)
并想要这样的输出:
((4 5 6) (3) (12 22) (4) (4 55) (43) (1 4) (0))
我想您可以猜测顺序,顺序是升序,我对Lisp完全陌生,需要一些帮助
答案 0 :(得分:2)
这是TXR Lisp中的一种可能的解决方案:
(defun ascending-partitions (list)
(let ((indices (mappend (do if (>= @1 @2) (list @3))
list (cdr list) (range 1))))
(split list indices)))
我们获得列表中元素的数字索引位置,这些位置不大于其前任元素;然后我们使用split
函数在这些索引处将列表切成碎片。
通过使用mappend
函数处理三个列表来完成索引的计算:原始list
,与删除了第一个元素(cdr list)
的相同列表并行,以及无限列表由(range 1)
产生的以1开始的整数递增。
do
宏为我们编写了一个匿名函数,其中嵌入表达式中的@1
,@2
和@3
变量是该变量的三个参数,按此顺序。 mappend
用从列表中并行获取的连续三重值调用此函数。因此,@1
从list
中获取值,@2
从(cdr list)
中获取连续值,@3
从整数列表中获取连续值。每当@1
至少与其后继@2
一样大时,我们会将位置索引@3
收集到一个元素列表中。 mappend
将这些链接在一起。
与此相反,我们可以编写一个更直接的解决方案,该解决方案需要更多代码,但可以更好地利用机器资源:
(defun ascending-partitions (list)
(let (partition output prev)
(each ((item list)) ;; use (dolist (item list) in Common Lisp
(when (and prev (<= item prev))
(when partition
(push (nreverse partition) output)
(set partition nil))) ;; use setf or setq in Common Lisp
(push item partition)
(set prev item)) ;; ditto
(when partition
(push (nreverse partition) output))
(nreverse output)))