モノのリスト (L と呼びます)、インデックス (N)、新しいモノ (NEW) があります。N の L のものを NEW に置き換えたい場合、これを行う最善の方法は何ですか? サブリストを N までと N からリストの最後まで取得し、リストを使用して最初の部分、NEW、および最後の部分から新しいリストを接着する必要がありますか? または、これを行うより良い方法はありますか?
10 に答える
(setf (nth N L) NEW)
トリックを行う必要があります。
どのくらいの頻度でこれを行う予定ですか。本当に配列が必要な場合は、配列を使用する必要があります。それ以外の場合は、最初の N 個の要素、新しい要素、末尾のコピーで構成される新しいリストを作成する関数で問題ありません。私は頭のてっぺんからビルトインを知りませんが、しばらく Lisp でプログラミングしていません。
これはSchemeでの解決策です(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)))))
(setf (nth N L) T)
やりたいことが「破壊的な」変更である場合、つまり既存のリストを実際に変更する場合は、最も明確で簡潔で最速の方法です。新しいメモリは割り当てられません。
私はちょうど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
hazzenのアドバイスは良いです(配列を使用してください)。おそらくこれらの破壊的な更新をたくさんやりたいと思うでしょうし、リストはランダムアクセスでは非常に非効率的です。これを行う最も簡単な方法
(setq A (make-array 5) :initial-contents '(4 3 0 2 1))
(setf (elt 2 A) 'not-a-number)
ここで、Aは配列です(ただしelt
、どのシーケンスでも機能します)。
ただし、機能する必要がある場合は、
- 古いリストと新しいリストの両方を維持したい
- 古いものと新しいものができるだけ多くのメモリを共有するようにします。
次に、hazzenのコードに相当するCommonLispを使用する必要があります。
(defun replace1 (list n elem)
(cond
((null list) ())
((= n 0) (cons elem list))
(t (cons (car list) (replace1 (cdr list) (1- n) elem)))))
これは遅いので見えます、そしてそれはおそらくそれが標準に含まれていない理由です。
hazzenのコードはSchemeバージョンです。これは、使用しているものであると便利です。
rplaca または replace のいずれかが必要なようです。http://www.lispworks.com/documentation/HyperSpec/Body/f_rplaca.htmまたはhttp://www.lispworks.com/documentation/HyperSpec/Body/f_replac.htm#replaceを参照してください。
[REPLACE][1] を使用します (T は Lisp の真の値であるため、T の代わりに X を使用します):
(replace L (list X) :start1 N)
[1]: http://www.lispworks.com/documentation/HyperSpec/Body/f_replac.htm REPLACE
list-replaceで JS を使用するとすぐに実行できます
他の人が指摘したように、明らかな解決策は遅く、メモリを使用します。可能であれば、リストに対して別の要素単位の操作を実行する必要があるまで、要素の置換を延期するようにしてください(loop for x in list do ...)
。
そうすれば、コンシング (メモリ) と反復 (CPU) を償却できます。
(defun replace-nth-from-list (list n elem)
(cond
((null list) ())
(t (append (subseq list 0 n) elem (subseq list (+ 1 n)(length list))))))