У меня есть список вещей (я назову его L), индекс (N) и новую вещь (NEW). Если я хочу заменить вещь в L на N с помощью NEW, что это лучший способ сделать это? Должен ли я получить подсписку до N и от N до конца списка, а затем склеить новый список из первой части, NEW и последней части, используя список? Или есть лучший способ сделать это?
Заменить элемент в списке в Common Lisp?
Ответ 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
Ответ 6
Похоже, вы хотите либо rplaca, либо заменить. См. http://www.lispworks.com/documentation/HyperSpec/Body/f_rplaca.htm или http://www.lispworks.com/documentation/HyperSpec/Body/f_replac.htm#replace p >
Ответ 7
Используйте [ЗАМЕНИТЬ] [1] (я использую X вместо вашего T, поскольку T - истинное значение в Lisp):
(replace L (list X) :start1 N)
[1]: http://www.lispworks.com/documentation/HyperSpec/Body/f_replac.htm REPLACE
Ответ 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))))))