Clisp:select 个给定长度的子列表

Clisp : select sublists with a given length

在 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))) ) )

如果你能给我一些线索,让我找到好的结果,那就太好了。

谢谢大家。

修改列表没有多大意义,因为在列表的头部保留原始引用很麻烦。 Return 一个新列表。

这是过滤操作。 Common Lisp 中常用的运算符是 remove-if-not(或 remove-if,或 remove,具体取决于条件)。它需要一个谓词 should return 是否应该保留该元素。在这种情况下,它似乎是 (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))

这return是一个满足条件的新列表。你可以这样称呼它 (let ((minlength-list (filter-by-min-length 2 raw-list))) …).

很多基础课程一开始坚持递归地使用cons单元的原始操作来进行教学。

第一次尝试通常会忽略可能的堆栈耗尽。在每一步,你首先看看你是否在最后(然后 return nil),第一个元素是否应该被丢弃(然后 return 对其余部分进行递归的结果),或者是否它应该保留(然后将其转换为递归结果)。

如果尾调用优化可用,您可以重构它以使用累加器。在每一步中,不是先递归然后 consing,而是将保留的值 cons 到累加器并将其传递给递归。最后,你没有 return nil,而是反转累加器和 return 那。

嗯,我找到了我想要的答案,在我挠头流血之后......

说真的,这是有效的解决方案(感谢对长度的更正帮助我找到解决方案^^):

(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))) ) )

非修改版本

(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) .在link中表示:

use defvar, defparameter, or let to introduce new variables. Use setf and setq to mutate existing variables. Using them to introduce new variables is undefined behaviour