[已解决] 怎么改进delete-nth?


#1

我没找到删除某个list的某个位置的函数,就自己写了一个,但是删除第一个元素遇到了问题:

(defun delete-nth (index seq)
  "Delete the INDEX th element of SEQ.
Return result sequence, SEQ is modified."
  (if (equal index 0)
      (progn
        (setcar seq (car (cdr seq)))
        (setcdr seq (cdr (cdr seq))))
    (setcdr (nthcdr (1- index) seq) (nthcdr (1+ index) seq))))

有没有什么办法写的简洁一点……或者有什么内置函数能解决?


#2

(delete (nth index seq) seq) 可以不?


#3
(defun nd (n list)
  (let ((end (nthcdr (1+ n) list)))
    (setf (nthcdr n list) nil)
    (nconc list end)))

你要的 destructive。


#4

delete会把所有equal的元素都删掉,

比如

(setq my-seq '(1 1 1 2 3 4))
(setq my-seq (delete (nth 0 my-seq) my-seq))
my-seq
;=> (2 3 4)

#5
(defun delete-nth (index seq) 
  (let ((element (nth index seq))) 
     (if element 
         (delete element seq)
       seq)))

#6

或者你直接找到 nth 位置以后, 先 split , 然后再 Join


#7
(defun delete-nth (n list)
  (append (subseq list 0 (1- n)) (nthcdr n list)))

@casouri 这个怎么样?

就是我说的先分成两半, 再把两个列表粘贴到一起.


#8

这个挺好的 :smile: 主要我想的是destructive的。(今天早上新学的词……)


#9

分两半的思路主要是以后再读好懂一点, 要不是自己的代码隔几个月自己都要看半天.


#10

哈哈哈,的确。每隔几个月看之前的代码像看💩一样


#11

我试了试,好像不太行

(defun nd (n list)
  (let ((end (nthcdr (1+ n) list)))
    (setf (nthcdr n list) nil)
    (nconc list end)))
;=> nd
(setq my-seq '(1 1 1 2 3 4))
;=> (1 1 1 2 3 4)
(nd 0 my-seq)
;=> (1 1 2 3 4)
my-seq
;=> (1 1 1 2 3 4)

#12

我讨厌写 cdr, car, cdar, cadr 这种, 过几天, 每次读代码, 都要根据当前的表达式一层一层的数, 心累. :sweat:


#13

告诉你一个小技巧, google 的时候用 lisp blablabla , 不要用 elisp blabla, lisp 高手相对于 elisp 高手要多很多, 然后很多 lisp 的代码拷贝到 emacs 里面是可以直接运行的. :stuck_out_tongue_closed_eyes:


#14

docstring写好的话,一般用的话也不用非得再看源码了。要是需要改可能就费点劲……


#15
(defun nd (n list)
  (let ((end (nthcdr (1+ n) list)))
    (setf (nthcdr n list) end)
    list))

改了。


#16

这个挺好的,不过destructive的有没有可能?

比如

(setq my-seq '(1 2 3 4))
;=> (1 2 3 4)

(delete-nth 0 my-seq)
;=> (3 4)

my-seq
;=> (2 3 4)

#17

不可能破壞性去除一個列表的头。因為头沒了整个表也沒了。


不可能就地(In-place)地删除列表的第一个元素
#18

感觉这么搞有点吃力不讨好,我还是用普通的返回新列表的方法吧

感谢 @manateelazycat @LdBeth :smile:


#19
(defmacro nd (n exp)
  (if (zerop n)
      `(progn
         (pop ,exp)
         ,exp)
    `(progn
       (setf (nthcdr ,n ,exp) (nthcdr ,(1+ n) ,exp))
       ,exp)))

#20

(zerop n) 分支可以省略吧?