Nilの値を含む可能性のあるClojureマップがあり、それらを削除する関数を作成しようとしていますが、あまり成功していません(これは初めてです)。
例えば。:
(def record {:a 1 :b 2 :c nil})
(merge (for [[k v] record :when (not (nil? v))] {k v}))
これにより、一連のマップが作成されますが、これはマージから期待したものではありません。
({:a 1} {:b 2})
私はを頂きたい:
{:a 1, :b 2}
your forリスト内包表記はマップのリストを返すため、このリストをオプションの引数としてマージ関数に適用する必要があります。
user> (apply merge (for [[k v] record :when (not (nil? v))] {k v}))
{:b 2, :a 1}
マップをシーケンスとしてフィルタリングし、マップに結合することによる、より簡潔なソリューション:
user> (into {} (filter second record))
{:a 1, :b 2}
削除しないでくださいfalse値:
user> (into {} (remove (comp nil? second) record))
{:a 1, :b false}
dissocを使用して、まったく新しいマップを作成する代わりに、永続的なデータ共有を許可します。
user> (apply dissoc
record
(for [[k v] record :when (nil? v)] k))
{:a 1, :b 2}
ネストされたマップで機能するものは次のとおりです。
(defn remove-nils
[m]
(let [f (fn [[k v]] (when v [k v]))]
(postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m)))
あなたはそれを地図に押しつぶすことができます:
(into {} (remove (fn [[k v]] (nil? v)) {:a 1 :b 2 :c nil}))
=> {:a 1 :b 2}
@Eelcoの答えのバリエーション:
(defn remove-nils [m]
(let [f (fn [x]
(if (map? x)
(let [kvs (filter (comp not nil? second) x)]
(if (empty? kvs) nil (into {} kvs)))
x))]
(clojure.walk/postwalk f m)))
@ broma0の要点として、空のマップはすべて削除されます。
user> (def m {:a nil, :b 1, :c {:z 4, :y 5, :x nil}, :d {:w nil, :v nil}})
user> (remove-nils m)
{:b 1, :c {:z 4, :y 5}}
user> (remove-nils {})
nil
JürgenHötzelソリューションがnil/falseの問題を修正するように改良されました
(into {} (filter #(not (nil? (val %))) {:a true :b false :c nil}))
@thnetosソリューションの少し短いバージョン
(into {} (remove #(nil? (val %)) {:a true :b false :c nil}))
reduce-kvを使用してキーを削除することもできます
(reduce-kv (fn [m key value]
(if (nil? value)
(dissoc m key)
m))
{:test nil, :test1 "hello"}
{:test nil, :test1 "hello"})
ユルゲンの(フィルターの2番目のレコード)アプローチは、最も気の利いたClojure Trickに投票しますが、今回はselect-keys
を使用して、別の方法で投げたいと思いました。
user> (select-keys record (for [[k v] record :when (not (nil? v))] k))
{:b 2, :a 1}
Reduceを使用できます。
user> (reduce (fn [m [k v]] (if (nil? v) m (assoc m k v))) {} record)
{:b 2, :a 1}
何らかの理由で順序を維持したい場合(通常、マップでは重要ではありません)、dissoc
を使用できます。
user> (reduce (fn [m [k v]] (if (nil? v) (dissoc m k) m)) record record)
{:a 1, :b 2}
これがマップとベクトルで機能するものです:
(defn compact
[coll]
(cond
(vector? coll) (into [] (filter (complement nil?) coll))
(map? coll) (into {} (filter (comp not nil? second) coll))))