Clisp:选择具有给定长度的子列表

时间:2018-06-27 22:26:42

标签: common-lisp clisp

使用Sublime Text处理CLISP。

Exp。在CLISP中:不到1年

我试图解决这个问题已经有一段时间了……可能没有成功……

实际上,我必须创建一个函数,该函数将修改列表并仅保留等于或大于给定数字的子列表(在下面观看)

我必须处理的列表:

(setq liste '((a b) c (d) (e f) (e g x) f))

我应该找到这个结果:

(lenght 2 liste) => ((a b) (e f) (e g x))
liste => ((a b) (e f) (e g x))

这是我的代码:

(defun lenght(number liste)
    (cond
        ((atom liste) nil)
        ((listp (car liste))
            (rplacd liste (lenght number (cdr liste))) )
        ((<= (lenght number (car liste)) number)
         (I don't know what to write) )
        ((lenght number (cdr liste))) ) )

如果您能给我一些线索以便让我找到好的结果,那将非常好。

谢谢大家。

3 个答案:

答案 0 :(得分:3)

修改列表没有多大意义,因为在列表的开头保留原始参考会变得毛茸茸。返回新列表。

这是一个过滤操作。为此,Common Lisp中常用的运算符是remove-if-not(或remove-ifremove,具体取决于条件)。它使用一个谓词,该谓词应返回是否应保留该元素。在这种情况下,它似乎是(lambda (element) (and (listp element) (>= (length element) minlength)))

(defun filter-by-min-length (minlength list)
  (remove-if-not (lambda (element)
                   (and (listp element)
                        (>= (length element) minlength)))
                 list))

在许多情况下,当在编译时知道条件时,loop会生成更快的编译代码:

(defun filter-by-min-length (minlength list)
  (loop :for element :in list
        :when (and (listp element)
                   (>= (length element) minlength))
          :collect element))

这将返回一个满足条件的新列表。您会像(let ((minlength-list (filter-by-min-length 2 raw-list))) …)这样称呼它。

许多基础课程一开始都坚持以递归方式使用cons单元上的原始操作进行教学。

第一次尝试通常会忽略可能的堆栈耗尽。在每个步骤中,您首先要查看是否在末尾(然后返回nil),是否应该丢弃第一个元素(然后返回其余部分递归的结果)或是否应保留(然后将其保留为递归结果)。

如果可以进行尾部调用优化,则可以将其重构为使用累加器。在每个步骤中,您无需先递归再进行约束,而是将保留的值约束到累加器上,并将其传递给递归。最后,您不返回nil,而是反转累加器并将其返回。

答案 1 :(得分:0)

好吧,在挠挠头直到流血……之后,我已经找到了想要的答案。

很抱歉,这是有效的解决方案(感谢对长度的修正,这有助于我找到解决方案^^):

(defun filter-by-min-length (min-length liste)
    (cond
        ((atom liste) nil)
        ((and (listp (car liste))(>= (length (car liste)) min-length))
            (rplacd liste (filter-by-min-length min-length (cdr liste))) )
        ((filter-by-min-length min-length (cdr liste))) ) )

答案 2 :(得分:0)

非修改版本

(defun filter-by-min-length (min-length le)
  (cond ((atom le) nil)
        ((and (listp (car le)) (>= (length (car le)) min-length))
         (cons (car le) (filter-by-min-length min-length (cdr le))))
        (t (filter-by-min-length min-length (cdr le)))))

测试:

(defparameter *liste* '((a b) c (d) (e f) (e g x) f))
(filter-by-min-length 2 *liste*)
;; ((A B) (E F) (E G X))
*liste*
;; ((A B) C (D) (E F) (E G X) F)  ; -> *liste* not modified

为了养成良好的习惯,我建议使用defparameter而不是setq,因为setq的行为可能并不总是定义的(请参见here)。在链接中说:

  

使用defvardefparameterlet引入新变量。使用setf   和setq来突变现有变量。用他们介绍新的   变量是不确定的行为