Clojure でマップのキーとバリューを反転させるのどーするの?
SWT のウィジェットのスタイルを設定したり、取得するとき、キーワードの配列として設定したり、取得したりすると便利だと思いますた。
キーの配列をビットフィールドに変換して .setStyle
に渡すのはうまくいったんだけど、
そのビットフィールドをキーワードの配列に変換して返さないとうまくないよなーこれということになり…。(あらすじ)
結局のところ、widgets.clj の 167 行目からの to-style-value
関数の様な形になったんだけど、ちょいと難しかった。
(defn- to-style-value [a_style-alist swt-style-value] (let [reverse-alist (apply assoc {} (interleave (vals a_style-alist) (keys a_style-alist))) has-vlist (filter pos? (map #(bit-and (a_style-alist %) swt-style-value) (keys a_style-alist)))] (map #(get reverse-alist %) has-vlist)))
第一引数の a_style-alist
が、キーワードと SWT のスタイルを表す定数のマップで、
第二引数の swt-style-value
は SWT のスタイル用定数を bit-or
でくっつけたもの。
let
内変数の reverse-alist
は a_style-alist
を反転させたもの。
(interleave (vals a_style-alist) (keys a_style-alist))
とやるだけでは、バリュー・値と並んだ配列になってしまうんだ。
これをマップにしてくれるのが apply
と assoc
。
ぶっちゃけると、なぜそーなるかは知らないw
(filter pos? (map #(bit-and (a_style-alist %) swt-style-value) (keys a_style-alist)))
swt-style-value
は SWT のスタイル定数のいずれかを必ず含んでいるので、 bit-and
を使うとどれを含んでいるのかがわかるよね。
ということでもうひとつの let
内変数の has-vlist
は swt-style-value
に含まれている SWT のスタイル定数の配列になってるよ。
これをキーに、reverse-alist
につっこむと、キーワードの配列を得ることができるよ!できるよ!
ヽ(゚∀゚)ノ ワー
P.S.
だんだん寒くなってきましたね。お元気ですか? 私は元気です。
このエントリを書いていたところ、私はあることに気づきました。
それは、let
の中の変数への値に (keys a_style-alist)
が共通して含まれていることです。
であれば:
(defn- to-style-value [a_style-alist swt-style-value] (let [style-keys (keys a_style-alist) reverse-alist (apply assoc {} (interleave (vals a_style-alist) style-keys)) has-vlist (filter pos? (map #(bit-and (a_style-alist %) swt-style-value) style-keys))] (map #(get reverse-alist %) has-vlist)))
このように書いてもいいのではないでしょうか?