Common Lisp: How to return a list without the nth element of a given list?

I have a question, how to return a list without the nth element of this list? For example, this list: (1 2 3 2 4 6) and the given n = 4 , in this case the returned list should be (1 2 3 4 6) .

+6
source share
8 answers

The simplest recursive solution:

 (defun remove-nth (n list) (declare (type (integer 0) n) (type list list)) (if (or (zerop n) (null list)) (cdr list) (cons (car list) (remove-nth (1- n) (cdr list))))) 

This will be a common tail, unless there are n or more elements in the list, in which case it returns a new list with the same elements as the one provided.

+8
source

Using remove-if :

 (defun foo (n list) (remove-if (constantly t) list :start (1- n) :count 1)) 

butlast / nthcdr solution (fixed):

 (defun foo (n list) (append (butlast list (1+ (- (length list) n))) (nthcdr n list))) 

Or maybe more readable:

 (defun foo (n list) (append (subseq list 0 (1- n)) (nthcdr n list))) 

Using loop :

 (defun foo (n list) (loop for elt in list for i from 1 unless (= in) collect elt)) 
+7
source

A slightly more general function:

 (defun remove-by-position (pred lst) (labels ((walk-list (pred lst idx) (if (null lst) lst (if (funcall pred idx) (walk-list pred (cdr lst) (1+ idx)) (cons (car lst) (walk-list pred (cdr lst) (1+ idx))))))) (walk-list pred lst 1))) 

What we use to implement the desired nth removal:

 (defun remove-nth (n list) (remove-by-position (lambda (i) (= in)) list)) 

And the call:

 (remove-nth 4 '(1 2 3 2 4 6)) 

Edit: Applied comments from Samuel's comment.

+1
source

Here is an interesting approach. It replaces the nth element of the list with a new character, and then removes that character from the list. I did not consider how effective it is!

 (defun remove-nth (n list) (remove (setf (nth n list) (gensym)) list)) 
+1
source

Make another function inside your function that has a counter that you can use to tell you when you found the nth element and use it, for example:

 (defun without-nth (mylist) (letfn (without-nth (mylist count) 

(- implement your search and delete the material here -)))

  (without-nth mylist 0))) 
0
source

My terrible elisp solution:

 (defun without-nth (list n) (defun accum-if (list accum n) (if (not list) accum (accum-if (cdr list) (if (eq n 0) accum (cons (car list) accum)) (- n 1)))) (reverse (accum-if list '() n))) (without-nth '(1 2 3) 1) 

Should be easily portable to Common Lisp.

0
source

A simpler solution would be as follows:

 (defun remove-nth (n lst) (append (subseq lst 0 (- n 1)) (subseq lst n (length lst))) ) 
0
source

Destructive version, the original list will be changed (except when n <1),

 (defun remove-nth (n lst) (if (< n 1) (cdr lst) (let* ((p (nthcdr (1- n) lst)) (right (cddr p))) (when (consp p) (setcdr p nil)) (nconc lst right)))) 

This is elisp, but I think these are standard lispy functions.

0
source

Source: https://habr.com/ru/post/909344/


All Articles