Reputation: 2948
Say I have a list of maps that looks like the following:
(def my-map '({:some-key {:another-key "val"}
:id "123"}
{:some-key {:another-key "val"}
:id "456"}
{:some-other-key {:a-different-key "val2"}
:id "789"})
In my attempt to filter this map by :another-key
, I tried this:
(filter #(= "val" ((% :some-key) :another-key)) my-map)))
However, this will throw a NullPointerException
on the map entry that doesn't contain the key I'm filtering on. What would be the optimal way to filter this map, excluding entries that don't match the filtered schema entirely?
Upvotes: 1
Views: 303
Reputation: 4713
Your first lookup of the key :some-key
will return nil
if the map key is not in the map. Calling nil
will result in the NPE you see.
The solution is easy, just make the keyword lookup itself in the map which work even if given a nil:
(def my-map '({:some-key {:another-key "val"}
:id "123"}
{:some-key {:another-key "val"}
:id "456"}
{:some-other-key {:a-different-key "val2"}
:id "789"}))
(filter #(= "val" (:another-key (% :some-key))) my-map)
You can also use get-in
:
(filter #(= "val" (get-in % [:some-key :another-key])) my-map)
And if your list could potentially have nil
items:
(filter #(= "val" (:another-key (:some-key %))) my-map)
Explanation:
(:k nil);; => nil
(nil :k);; => NPE
({:k 4} :k);; => 4
(:k {:k 4});; => 4
;; BTW, you can also specify the "not found" case:
(:k nil :not-there);; => :not-there
See also the clojure style guide.
Upvotes: 2