Удалить только первое появление элемента в списке? - PullRequest
3 голосов
/ 20 декабря 2010

Как удалить только первое появление элемента в списке (elisp)?

Ответы [ 3 ]

8 голосов
/ 08 января 2011

Функции Common Lisp для редактирования последовательности (remove и друзья) принимают аргумент ключевого слова :count:

Количество , если имеетсяограничивает количество удаляемых или удаляемых элементов;если тест удовлетворяет более чем count , то из этих элементов удаляются или удаляются только самые левые или самые правые, в зависимости от from-end , столько, сколько указано кол .Если 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*.)

2 голосов
/ 24 декабря 2010

Код нуба для elisp.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))
  ))
)

Чтобы удалить 3 из mylist, будет называться

>(setq mylist '(1 2 3 4 3 3))
>(setq mylist (remove-first 3 mylist))
(1 2 4 3 3)
1 голос
/ 20 декабря 2010

Вы можете использовать этот 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))
...