警告:绝对Lisp n00b。我非常精通Java,而且在C. Lisp中适度...到目前为止还不是我最喜欢的。 (但它比prolog更好......)
我想迭代列表并优先返回该列表的子集。
我已经成功编写了代码,它将拆分列表并在堆栈使用(append)函数展开时重建它。但是,当我试图投入条件时,我会遇到很大麻烦。
(defun split-then-rebuild-list (row value llist)
(cond ((not (eq llist nil))
(let ((item (first llist))
(rval nil))
(print llist)
(print "Entering next recursion level")
(setf rval (split-then-rebuild-list row value (cdr llist)))
(print "Left recursion")
(print "Current item: ")
(princ item)
(print "Received: ")
(Princ rval)
(print "Appended:")
(setf x (first(first item)))
(and (eq row x) (eq value (nth 2 (first item)))
(print "gluing: ")
(princ rval)
(princ item)
(setf rval (append rval item )))))))
NIL只是随着它的展开而不断向上返回。我不明白的是,为什么当我输入(set tmp (list A B C) )
然后(append tmp nil)
时,它会返回(A B C)
,但不会返回代码,因为我在此处输入了(defun splitThenRebuildList( llist )
(cond(
(not (eq llist nil ))
(let(
(item (first llist))
(rval)
);end let decl
(print llist )
(setf rval (splitThenRebuildList( cdr llist )))
(print "item: ")(princ item)
(print "Received: ") (Princ rval)
(append rval item )
);end let
));end cond
)
。对我来说,我会以这样的方式阅读:“在所有情况下都返回nil,但在这些条件下返回列表。如果两个列表项符合条件,它们将被附加,否则它应该只返回前一个递归级别的列表。
[EDITED]提供更多信息 我的原始功能适用于拆分和重建:
{{1}}
任何建议修改此内容以获得自首次发布代码后我需要的内容是堕胎吗?
答案 0 :(得分:2)
在对您的问题的评论中,我建议remove-if-not
。这是一个使用它的例子,它做我想你自己的函数试图做的事情。这是你打算与否?
(defun filter-by-row-and-value (row value seq)
(remove-if-not (lambda (x)
(and (eql row (first x))
(eql value (third x))))
seq
:key #'first))
正如其他人已经注意到的那样,你自己的代码没有达到预期的原因可能是你将调试输出语句放在and
表单中。对于那个具体案例,我建议使用
(when (and conditions...)
debugging-output
return-value)
而不是
(and conditions...
debugging-output
return-value)
答案 1 :(得分:0)
很难说出你想要做什么。以下是您可能尝试做的事情的示例。
这是一个获取值和列表的函数,并返回列表的子集,其元素是车辆为eq
到3
的cons对。如果需要,可以使测试更复杂。
(defun do-something-to-list (value list)
(cond ((null list)
nil)
((eq value (first (first list)))
(cons (first list)
(do-something-to-list value (rest list))))
(t
(do-something-to-list value (rest list)))))
行动中:
(do-something-to-list 3 '((3 9) (a b c) (47 3) (3 zztop) (blah)))
((3 9) (3 zztop))
注意:在common-lisp中使用内置例程有很多方法可以做这种事情,但看起来你只是想学习如何理解递归。
答案 2 :(得分:0)
如果您从代码中删除(princ rval)
和(princ item)
,则该功能有效。
(split-then-rebuild-list :a 4 '(((:a nil 4))((:b nil 5))))
=> ((:无4))
要在递归展开时重建列表,请在匹配项的测试为false时返回值。