lisp过滤掉列表中不匹配谓词的结果

Any*_*orn 35 lisp elisp predicate list filter

我正在尝试学习lisp,使用emacs方言,我有一个问题.让我们说list有一些成员,谓词的评估结果为false.如何在没有这些成员的情况下创建新列表?类似的东西{ A in L: p(A) is true }.在python中有过滤函数,在lisp中是否有相同的东西?如果没有,我该怎么办?

谢谢

小智 42

这些函数在CL包中,您需要(require 'cl)使用它们:

(remove-if-not #'evenp '(1 2 3 4 5))
Run Code Online (Sandbox Code Playgroud)

这将返回一个包含参数中所有偶数的新列表.

同时查找delete-if-not,它也会相同,但会修改其参数列表.

  • 我想指出函数`#'remove-if-not`在Common Lisp [¹]中已被弃用(http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body /fun_removecm__elete-if-not.html)其中过滤器将写成`(remove-if(complement#'evenp)'(1 2 3 4 5))`或简单`(remove-if#'oddp'(1 2 3 4 5))` - 据我所知,Emacs Lisp中不存在函数`complement`. (6认同)
  • 请使用*cl-lib*包,并使用**cl-remove-if-not**函数作为替换. (4认同)

Mir*_*lov 21

如果您在代码中大量操作列表,请使用dash.el现代函数编程库,而不是编写样板代码并重新发明轮子.它具有处理您可以想象的列表,树,函数应用程序和流控制的所有功能.保留与谓词匹配的所有元素并删除您需要的其他元素-filter:

(-filter (lambda (x) (> x 2)) '(1 2 3 4 5)) ; (3 4 5)
Run Code Online (Sandbox Code Playgroud)

感兴趣的其他功能包括-remove,-take-while,-drop-while:

(-remove (lambda (x) (> x 2)) '(1 2 3 4 5)) ; (1 2)    
(-take-while (lambda (x) (< x 3)) '(1 2 3 2 1)) ; (1 2)
(-drop-while (lambda (x) (< x 3)) '(1 2 3 2 1)) ; (3 2 1)
Run Code Online (Sandbox Code Playgroud)

什么是伟大的大约dash.el是它支持照应宏.回指宏的行为与函数类似,但它们允许使用特殊语法使代码更简洁.而不是提供匿名函数作为参数,只需编写一个s表达式并使用it而不是局部变量,就像x前面的例子一样.相应的照应宏以2个破折号开头而不是1个:

(--filter (> it 2) '(1 2 3 4 5)) ; (3 4 5)
(--remove (> it 2) '(1 2 3 4 5)) ; (1 2)
(--take-while (< it 3) '(1 2 3 2 1)) ; (1 2)
(--drop-while (< it 3) '(1 2 3 2 1)) ; (3 2 1)
Run Code Online (Sandbox Code Playgroud)


kjf*_*tch 19

昨晚我一直在寻找同样的东西,并在EmacsWiki看到Elisp Cookbook.列表/序列部分包含过滤技术,并说明如何使用和完成此操作.我不得不修改代码以将其用于我自己的目的,但这是原始的:mapcardelq

;; Emacs Lisp doesn’t come with a ‘filter’ function to keep elements that satisfy 
;; a conditional and excise the elements that do not satisfy it. One can use ‘mapcar’ 
;; to iterate over a list with a conditional, and then use ‘delq’ to remove the ‘nil’  
;; values.

   (defun my-filter (condp lst)
     (delq nil
           (mapcar (lambda (x) (and (funcall condp x) x)) lst)))

;; Therefore

  (my-filter 'identity my-list)

;; is equivalent to

  (delq nil my-list)

;; For example:

  (let ((num-list '(1 'a 2 "nil" 3 nil 4)))
    (my-filter 'numberp num-list))   ==> (1 2 3 4)

;; Actually the package cl-seq contains the functions remove-if and remove-if-not. 
;; The latter can be used instead of my-filter.
Run Code Online (Sandbox Code Playgroud)


Joe*_*mob 5

Emacs现在带有库seq.el,请使用seq-remove

seq-remove (pred sequence) 
"Return a list of all the elements for which (PRED element) is nil in SEQUENCE."
Run Code Online (Sandbox Code Playgroud)