web-dev-qa-db-ja.com

Common Lispのリストのアイテムを置き換えますか?

私は物事のリスト(私はそれをLと呼びます)、インデックス(N)と新しいもの(NEW)を持っています。 NのLにあるものをNEWに置き換えたい場合、これを行うための最良の方法は何ですか?サブリストをNまで、Nからリストの最後まで取得してから、リストを使用して最初の部分、NEW、最後の部分から新しいリストを接着する必要がありますか?または、これを行うためのより良い方法はありますか?

24
Paul Wicks
(setf (nth N L) NEW)

トリックを行う必要があります。

26
l0st3d

どのくらいの頻度でこれを行いますか。本当に配列が必要な場合は、 array を使用する必要があります。そうでなければ、はい、最初の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)))))
8
hazzen
(setf (nth N L) T)

実行したいことが「破壊的な」変更である場合、つまり実際に既存のリストを変更する場合は、が最も明確で、最も簡潔で、最速の方法です。新しいメモリは割り当てられません。

7
Dan Weinreb

私は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

4
user25281

hazzenのアドバイスは良いです(配列を使用してください)。おそらくこれらの破壊的な更新をたくさんやりたいと思うでしょうし、リストはランダムアクセスでは非常に非効率的です。これを行う最も簡単な方法

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

ここで、Aは配列です(ただし、eltは任意のシーケンスで機能します)。

ただし、が機能している必要がある場合、つまり

  1. 古いリストと新しいリストの両方を維持したい
  2. 古いものと新しいものができるだけ多くのメモリを共有するようにします。

次に、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バージョンです。これは、使用しているものであると便利です。

すぐにJSでそれを行うことができます list-replace

1
Madil

[REPLACE] [1]を使用します(TはLISPの真の値であるため、Tの代わりにXを使用します):

(replace L (list X) :start1 N)

[1]: http://www.lispworks.com/documentation/HyperSpec/Body/f_replac.htm 交換

1
Kim Minh Kaplan
1
David Plumpton

他の人が指摘しているように、明らかな解決策は遅く、メモリを使用します。可能であれば、リストで別の要素ごとの操作を実行する必要があるまで、要素の置き換えを延期するようにしてください。 (loop for x in list do ...)

そうすれば、consing(メモリ)とiteration(cpu)を償却します。

0
Mikael Jansson