仅删除元素首次出现在列表中?

时间:2010-12-20 15:53:03

标签: elisp

如何仅删除元素首次出现在列表中(elisp)?

3 个答案:

答案 0 :(得分:8)

Common Lisp sequence-editing functionsremove和朋友)采用:count关键字参数:

  

计数,如果提供,则限制删除或删除的元素数量;如果超过 count 元素满足测试,那么这些元素只会删除或删除最左边或最右边(取决于 from-end ),与< EM>计数的。如果提供了 count 且为负数,则行为就像是提供了零而已。如果 count nil,则所有匹配项都会受到影响。

例如:

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)

(请注意,Emacs已有自己的名为remove的函数,因此cl包必须使用名称remove*。)

答案 1 :(得分:2)

elisp的noob代码。 position可以找到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))
  ))
)

要从mylist中删除3,将被称为

>(setq mylist '(1 2 3 4 3 3))
>(setq mylist (remove-first 3 mylist))
(1 2 4 3 3)

答案 2 :(得分:1)

您可以使用此elisp(需要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)))

注意:这会生成原始列表的副本。对于使用副作用的人,请尝试:

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

注意:当第一个元素被移除时,只返回cdr,因此一如既往地使用这种类型的操作,如下所示调用它:

(setq mylist (remove-first* 3 mylist))