How to delete only first appearance of e开发者_运维技巧lement into list (elisp) ?
The Common Lisp sequence-editing functions (remove
and friends) take a :count
keyword argument:
Count, if supplied, limits the number of elements removed or deleted; if more than count elements satisfy the test, then of these elements only the leftmost or rightmost, depending on from-end, are deleted or removed, as many as specified by count. If count is supplied and negative, the behavior is as if zero had been supplied instead. If count is
nil
, all matching items are affected.
For example:
ELISP> (require 'cl)
cl
ELISP> (remove* 1 '(1 2 1 3 1 4) :count 1)
(2 1 3 1 4)
ELISP> (remove* 1 '(1 2 1 3 1 4) :count 2)
(2 3 1 4)
ELISP> (remove* 1 '(1 2 1 3 1 4) :count 2 :from-end t)
(1 2 3 4)
(Note that Emacs already had its own function called remove
, so the cl
package has to use the name remove*
.)
The noob's code for elisp. position
can be found into cl-seq.el
.
(defun remove-first (elem lst)
(interactive)
(if (equal (position elem lst) nil ) (progn (setq lst lst) )
(progn
(setq out1 (nthcdr (+ 1 (position elem lst)) lst))
(setq out2 (nbutlast lst (- (length lst) (position elem lst) ) ) )
(delq nil (append out2 out1))
))
)
To remove 3 from mylist, will be called as
>(setq mylist '(1 2 3 4 3 3))
>(setq mylist (remove-first 3 mylist))
(1 2 4 3 3)
You can use this elisp (which requires cl
):
(defun remove-first (elt seq)
(let ((remove-first t))
(remove-if (lambda (e) (when (and remove-first (equal elt e))
(setq remove-first nil)
t))
seq)))
Note: this makes a copy of the original list. For one using side-effects, try this:
(defun remove-first* (elt seq)
(if (equal elt (car seq))
(cdr seq)
(while (cdr seq)
(if (equal elt (cadr seq))
(progn (setcdr seq (cddr seq))
(setq seq nil))
(setq seq (cdr seq))))
seq))
Note: when the first element is the one removed, just the cdr
is returned, so as always with this type of operation, invoke it like so:
(setq mylist (remove-first* 3 mylist))
精彩评论