如何在没有地图的情况下在 Lisp 中创建子列表列表?
How to create a list of sublists in Lisp without map?
我正在尝试创建一个函数来创建给定列表中所有子列表的列表。
我的意思是,当我有一个列表时:
(4 (a g b) g (1 2 3) g (4 5 6))
我想要一个列表:
((a g b) (1 2 3) (4 5 6))
我目前得到的:
(defun unterlisten_zurueckgeben (lst)
(let (unterlisten)
(cond ((endp lst) nil)
((listp (first lst))
(or (unterlisten_zurueckgeben (first lst))
(setq unterlisten (cons (first lst) (unterlisten_zurueckgeben (rest lst))))))
(t (unterlisten_zurueckgeben (rest lst))))
unterlisten))
似乎不起作用,我找不到我的错误。
如果是这样你可以写:
(defun unterlisten-zurueckgeben (lst)
(remove-if-not #'listp lst))
; or use #'consp if you don't want empty sublists
请注意,在 Lisp 中,组合标识符的首选方式是使用破折号而不是下划线。
所以你只想保留子列表。您可以使用 remove-if
:
(defun remove-atoms (lst)
(remove-if #'atom lst))
在你的递归代码中有一个问题:
(or (unterlisten_zurueckgeben (first lst))
(setq unterlisten (cons (first lst)
(unterlisten_zurueckgeben (rest lst))))))
这里如果(unterlisten_zurueckgeben (first lst))
的结果不是一个空列表(例如一个列表有一个列表)那么它将是整个结果。
如果不是 nil
,那么您将 local 绑定 underlisten
更改为看起来不错的结果。
因为 cond
是 而不是 尾部表达式。函数的结果总是 underlisten
是什么。因此,对于默认情况下,您只是对列表的其余部分进行递归,结果永远不会 returned,因为它将 return nil
(underlisten
的初始值)。
因此,即使是您的递归式自己解决方案也比需要的复杂得多:
(defun remove-atoms (lst)
(cond ((endp lst) nil)
((listp (first lst))
(cons (first lst) (remove-atoms (rest lst))))
(t (remove-atoms (rest lst)))))