web-dev-qa-db-ja.com

リストの最後にアイテムを追加するための「短所」とは何ですか?

リストの最後にアイテムを追加する一般的な方法は何ですか?

リスト(1 2 3)があり、それに4を追加したい(4は評価の結果(+ 2 2))

(setf nlist '(1 2 3))  
(append nlist (+ 2 2))  

これは、appendが数値ではなくリストを期待していることを示しています。どうすればこれを達成できますか?

15
r b

append を使用できますが、ループまたは非常に長いリストで使用すると、パフォーマンスが低下する可能性があることに注意してください。

(append '(1 2 3) (list (+ 2 2)))

パフォーマンスが重要な場合、通常のイディオムは、先頭に( cons を使用して)、次に reverse (または nreverse )を付けてリストを作成することです。

27
danlei

LISPの種類を指定していないので、Emacs LISPと dash リスト操作ライブラリを使用すると、関数 -snoc 要素が最後に追加された新しいリストを返します。名前が逆になっている「短所」。

(-snoc '(1 2) 3) ; (1 2 3)
6

「最前線の短所、逆にして終了する」というイディオムが適切でない場合(たとえば、構築中にリストを他の関数に渡す必要がある場合)、「終了を追跡する」もあります。騙す。ただし、リストの先頭を確認してリストを作成し、最後に使用する前に、reverseまたはnreverseを使用して終了する方がおそらくクリーンです。

本質的に、これにより、リストを追跡する必要がありますが、リストを作成するときに正しい順序でリストを作成できます。

(defun track-tail (count)
  (let* ((list (cons 0 nil))
     (tail list))
    (loop for n from 1 below count
       do (progn
        (setf (cdr tail) (cons n nil))
        (setf tail (cdr tail))
        (format t "With n == ~d, the list is ~a~%" n list)))
    list))

これにより、次の出力が得られます。

CL-USER> (track-tail 5)
With n == 1, the list is (0 1)
With n == 2, the list is (0 1 2)
With n == 3, the list is (0 1 2 3)
With n == 4, the list is (0 1 2 3 4)
(0 1 2 3 4)
6
Vatine

nconc を使用してリストを作成することもできます。これはappendのようなもので、入力リストの構造を変更するだけです。

(nconc nlist (list (+ 2 2)))
4
Trey Jackson

この関数は、状況によっては便利な場合があります。つまり、単一の要素をリストに透過的に追加します。つまり、リストを変更しますが、追加された要素(リストで囲まれている)を返します。

(defun attach1 (lst x)
  (setf (cdr (last lst)) (cons x nil)))

;; (attach1 nlist (+ 2 2)) ; append without wrapping element to be added in a list
3
mmj

たとえば_(1 2 3) + (1 2 3)_のように2つのリストを追加しようとしている場合、ここにコードがあります(再帰的)

_(defun add-to-all (x y)
    (T (appendl (+ (first x) (first y)) (add-to-all (tail x) (tail y)) ))
)
_

2番目のリストの最後にアイテムを追加しようとしている場合、たとえば3 + (1 2 3)

_(defun add-to-all (x y)
  (cond ((null? y) nil)
    (T (appendl (+ (first x) (first y)) (add-to-all (tail x) (tail y)) ))
  )
)
_
1
Giri

(追加l(リストe)); eは、リストの最後に追加する要素です。

1
Nadhem Jemmali

リストの最後の問題は、次の機能で実現できます。

(defun cons-last (lst x)
  (let ((y (copy-list lst))) (setf (cdr (last y)) (cons x nil)) y))

;; (cons-last nlist (+ 2 2))
1
mmj

リストを変更せずに特定のリストの最後にアイテムを追加したい場合は、前に提案したように、次のような関数を使用できます。

(defun annex (lst item)
  "Returns a new list with item added onto the end of the given list."
  (nconc (copy-list lst) (list item)))

これにより、入力リストを保持したまま、新しい拡張リストが返されます。ただし、追加されたアイテムを含めるように入力リストを変更する場合は、次のようなマクロを使用できます。

(define-modify-macro pushend (item)
  (lambda (place item)
    (nconc place (list item)))
  "Push item onto end of a list: (pushend place item).")

PushendはPushのように動作しますが、指定されたリストの最後にアイテムを「プッシュ」します。また、引数の順序はプッシュの逆であることに注意してください。

0
davypough