Подтвердить что ты не робот

Заменить элемент в списке в Common Lisp?

У меня есть список вещей (я назову его L), индекс (N) и новую вещь (NEW). Если я хочу заменить вещь в L на N с помощью NEW, что это лучший способ сделать это? Должен ли я получить подсписку до N и от N до конца списка, а затем склеить новый список из первой части, NEW и последней части, используя список? Или есть лучший способ сделать это?

4b9b3361

Ответ 1

(setf (nth N L) NEW)

должен сделать трюк.

Ответ 2

Как часто вы собираетесь это делать; если вам действительно нужен массив, вы должны использовать массив . В противном случае, да, функция, которая создает новый список, состоящий из копии первых элементов N, нового элемента и хвоста, будет в порядке. Я не знаю о встроенной верхней части головы, но я не программировал в Lisp через некоторое время.

Вот решение на Схеме (потому что я знаю это лучше, чем Common Lisp, и у меня есть интерпретатор для проверки моей работы):

(define (replace-nth list n elem)
  (cond
    ((null? list) ())
    ((eq? n 0) (cons elem (cdr list)))
    (#t (cons (car list) (replace-nth (cdr list) (- n 1) elem)))))

Ответ 3

(setf (nth N L) T)

является самым ясным, самым кратким и быстрым способом, если то, что вы хотите сделать, - это "разрушительная" модификация, т.е. фактически изменить существующий список. Он не выделяет никакой новой памяти.

Ответ 4

hazzen advice хорош (используйте массивы), так как вы, вероятно, захотите сделать много этих деструктивных обновлений, а списки очень неэффективны при произвольном доступе. Самый простой способ сделать это

(setq A (make-array 5) :initial-contents '(4 3 0 2 1))
(setf (elt 2 A) 'not-a-number)

где A - массив (хотя elt работает для любой последовательности).

Однако, если вы должны быть функциональными, то есть

  • Вы хотите сохранить как старые, так и новые списки
  • Вы хотите, чтобы старые и новые делили как можно больше памяти.

Затем вы должны использовать общий Lisp эквивалент кода hazzen:

(defun replace1 (list n elem)
  (cond
    ((null list) ())
    ((= n 0) (cons elem list))
    (t (cons (car list) (replace1 (cdr list) (1- n) elem)))))

Это выглядит медленным, потому что это так, и, вероятно, почему он не включен в стандарт.

hazzen code - это версия Scheme, которая полезна в том, что вы используете.

Ответ 5

Я просто пытаюсь исправить код hazzen:

(define (replace-nth list n elem)
  (cond 
    ((null? list) ())
    ((eq? n 0) (cons elem list))
    (#t (cons(car list) (replace-nth (cdr list) (- n 1) elem)))))

> (replace-nth (list 3 2 9 2) 2 8)
(3 2 8 9 2)

Этот код вставил новый элемент в список. Если мы хотим заменить элемент:

(define (replace-nth list n elem)
  (cond 
    ((null? list) ())
    ((eq? n 0) (cons elem (cdr list)))
    (#t (cons(car list) (replace-nth (cdr list) (- n 1) elem)))))

> (replace-nth (list 3 2 9 2) 2 8)
(3 2 8 2)

0 <= n <= длина (список) - 1

Ответ 8

быстро вы можете сделать это с помощью JS на list-replace

Ответ 9

Очевидное решение медленное и использует память, как отмечают другие. Если возможно, вам следует попытаться отложить замену элементов (элементов) до тех пор, пока вам не понадобится выполнить еще одну элементарную операцию в списке, например. (loop for x in list do ...).

Таким образом, вы будете амортизировать consing (память) и итерацию (cpu).

Ответ 10

(defun replace-nth-from-list  (list n elem)  
      (cond  
        ((null list) ())  
        (t (append (subseq list 0 n) elem (subseq list (+ 1 n)(length list))))))