リストの破壊的操作

リストの破壊的操作をする - 象徴ヶ淵 経由http://cadr.g.hatena.ne.jp/g000001/20090521/1242909362 の問題

nalist-to-plist

(nalist-to-plist '((foo . 1) (bar . 2) (baz . 3)))
=> (foo 1 bar 2 baz 3)

らしい。(key1 value1 key2 value2 ...) という list を plist と呼ぶことをはじめて知った。最初は (get 'symbol 'property-name) のことかと思った。

そもそも、これを読んで「へぇーへぇーへぇー」とか言ってた。

alist 例.((foo . 1) (bar .2) ...)とplist 例.(foo 1 bar 2 ....)の使うコンスセル数は同じことが知られています。

http://cadr.g.hatena.ne.jp/g000001/20090521/1242909362

手動で展開(?)してみると確かに同じだ。へぇーへぇーへぇー。

((foo . 1) . ((bar . 2) . nil)) ;4こ

(foo . (1 . (bar . (2 . nil)))) ;4こ


んで、40分ほどかかってできたのがこれ。

(defun nalist-to-plist (alist)
  (if (null alist)
      nil
    (let ((car (car alist))
          (cdr (cdr alist)))
      (setf (car alist) (car car)
            (cdr alist) car
            (car car) (cdr car)
            (cdr car) (nalist-to-plist cdr))
      alist)))
=> nalist-to-plist

(nalist-to-plist '((foo . 1) (bar . 2) (baz . 3)))
=> (foo 1 bar 2 baz 3)

nplist-to-alist

こっちは7分くらいでできた。

(defun nplist-to-alist (plist)
  (if (null plist)
      nil
    (let ((cadr (cadr plist))
          (cdr (cdr plist)))
      (setf (car cdr) plist
            (cdr plist) cadr
            (cdr cdr) (nplist-to-alist (cdr cdr)))
      cdr)))
=> nplist-to-alist

(nplist-to-alist '(foo 1 bar 2 baz 3))
=> ((foo . 1) (bar . 2) (baz . 3))

説明はしない(ぇー