3

次のタイプのリストがあります

(("abc" "12" "45")
 ("abc" "34" "56")
 ("cdb" "56" "78")
 ("deg" "90" "67")
 ("deg" "45" "34"))

そして、望ましい出力は

(("abc" "12" "45" "34" "56")
 ("cdb" "56" "78")
 ("deg" "90" "67" "45 "34)).

Lispで同じことをするための正しいアプローチは何ですか?

4

6 に答える 6

3

Common Lisp では、1 つの可能性は次のようなものです。

(defun merge-lists (lists)
  (let ((rv (make-hash-table :test #'equal)))
         (mapcar (lambda (list)
           (mapcar (lambda (x) (push x (gethash (car list) rv nil))) (cdr list)))
                   lists)
    (loop for key being the hash-keys of rv
          collect (cons key (reverse (gethash key rv))))))
于 2013-05-15T20:32:07.180 に答える
1

このスレッドにはすでに多くの素晴らしい回答があります。しかし、Common Lisp 集合演算については誰も言及していないので、私は自分自身でパイプすることにしました。

あなたがデータであると仮定すると、実際には次のようになります。

'((("abc") ("12" "45"))
  (("abc") ("34" "56"))
  (("cdb") ("56" "78"))
  (("deg") ("90" "67"))
  (("deg") ("45" "34")))

、つまり、値のシーケンスとペアになったキーのテーブル。そして、あなたが望むのは、与えられたキーの値を追加するだけでなく、マージすることです.Common Lispには、それを行うための一連の単純な操作があります. assocとを使用するだけunionです。ユニオンは次のように機能することに注意してください。

(setf record1 '("abc" "12" "34" "56"))
(setf record2 ' ("abc" "56" "45" "43"))
(union (cdr record1) (cdr record2) :test #'string=)

=> ("34" "12" "56" "45" "43")

assocリストのリストからキー値テーブルを作成できます。次のように、いくつかのアクセス関数を追加して、基になる表現を抽象化できます。

(defun get-record (table key)
  (assoc key table :test #'string=))

(defun merge-records (record1 record2)
  (if (not record1) 
      record2
          (cons (car record1) 
        (union (cdr record1) (cdr record2) :test #'string=))))

(defun insert-record (table record)
  (cons (merge-records record (get-record table (car record))) table))

したがって、テストデータを使用して:

(setf raw-data '(("abc" "12" "45")
    ("abc" "34" "56")
    ("abc" "45" "43")  ;; Note, duplicate value 45 to illustrate usage of union.
    ("cdb" "56" "78")
    ("deg" "90" "67")
    ("deg" "45" "34")))

テーブルにデータをロードします。

(setf data-table (reduce  #'insert-record raw-data :initial-value '()))

テーブルを印刷します。

(mapcar (lambda (key) (get-record data-table key)) '("abc" "cdb" "deg"))

==> (("abc" "12" "34" "56" "45" "43") ("cdb" "78" "56") ("deg" "34" "45" "67" "90"))

もちろん、連想リストは、挿入にも値の検索にもあまり効率的ではありません。しかし、それらは非常に便利に使用できるため、一般的なワークフローは、alist ソリューションを使用してソリューションを開発し、アクセス関数を使用して実際の実装を抽象化し、問題の理解を明確にして実装を固めるというものです。 、より効率的なデータ構造を選択してください-もちろん、それが実際のパフォーマンスに違いをもたらす場合.

于 2014-03-17T05:43:01.917 に答える