开发者

Delete only first appearance of element into list?

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜