3

この連想リストのリストを変換したい:

(setq terms '((("name" . "t1c1")
               ("taxonomy" . "category"))
              (("name" . "t1c2")
               ("taxonomy" . "category"))
              (("name" . "t1k1")
               ("taxonomy" . "post_tag"))
              (("name" . "t1k2")
               ("taxonomy" . "post_tag"))
              (("name" . "t1k3")
               ("taxonomy" . "post_tag"))))

この他の連想リストのリストに:

(("category" "t1c1" "t1c2")
 ("post_tag" "t1k1" "t1k2" "t1k3"))

私は思いついた:

(reduce
 '(lambda (lists term)
    (let* ((name (cdr (assoc "name" term)))
           (taxonomy (cdr (assoc "taxonomy" term)))
           (existing (assoc taxonomy lists)))
      (if existing
          (progn
            (setcdr existing (sort (cons name (cdr existing)) 'string<)))
        (push (list taxonomy name) lists)))
    lists)
 terms
 :initial-value nil)

これは洗練されていないように思えます --- let* と if ステートメントの使用は、どちらも潜在的なコードの匂いのように思えます。

elispでこれを行うためのより良い方法の例をいただければ幸いです---より良いとは、より純粋に機能的で、組み込み関数をより適切に使用して特定の操作を表現することなどを意味します.

ああ、結果の連想リストの内容をソートしたいと思います---出力をテストしやすくします。

4

2 に答える 2

2

頭に浮かぶ最もエレガントな方法は、(loop ...)マクロを使用することです。それは elisp 的ではないと主張する人もいるかもしれませんが、簡潔さと表現力が純粋さを上回っていると思います。

(loop
 with result = '()
 for term in terms
 for name = (aget term "name")
 for taxonomy = (aget term "taxonomy")
 do (aput 'result taxonomy
          (sort (cons name (aget result taxonomy)) 'string<))
 finally return result)
于 2013-03-27T15:47:30.217 に答える
1

elispでこれを行うためのより良い方法の例をいただければ幸いです---より良いとは、より純粋に機能的で、組み込み関数を使用して特定の操作を表現することなどを意味する場合があります.

おそらく次のようなものです(ロードされていると仮定しcl-libます):

(cl-flet ((step (lists term)
            (let ((name (aget term "name"))
                  (taxonomy (aget term "taxonomy")))
              (cl-acons taxonomy
                        (sort (cons name (aget lists taxonomy)) #'string<)
                        (cl-remove taxonomy lists :key #'car :test #'equal)))))
  (reduce #'step dhl-terms :initial-value nil))

「より純粋に機能的」も使用しないことを意味するため、ソリューションよりも効率的ではありませんsetcdr。新しいエントリをconsし、古いエントリを削除するためにもう一度パスを作成します。

于 2013-03-27T16:26:09.200 に答える