Neel
Neel

Reputation: 428

Extract list of hashmaps from clojure vector which has a specific value

I have a Clojure vector containing hashmaps. These hashmaps are not associated with any key themselves. But all of these hashmaps have a common key — lets say "ckey". I want to extract the those hashmaps whose "ckey" has the value "test".

The data is actually a parsed json. Something like this:-

testdata :{
sample1 : "samplevalue1"
sample2 : "samplevalue2"
sample3 : {innersample3 : "innersamplevalue3"}
sample4 : "samplevalue4"
sample5 : [{moresample [] 
           link {innersample5 : "innersamplevalue5"} 
           ckeydata [{ckey:"test" something: somethingValue something2: somethingValue2}]}
         {moresample [] 
           link {innersample5 : "innersamplevalue5"} 
           ckeydata [{ckey:"test1"something: somethingValue something2: somethingValue2}]}
         {moresample [] 
           link {innersample5 : "innersamplevalue5"} 
           ckeydata [ {ckey:"test2" something: somethingValue something2: somethingValue2}]}
         {moresample [] 
           link {innersample5 : "innersamplevalue5"} 
           ckeydata [ {ckey:"test" something: somethingValue something2: somethingValue2}]}]}

So in this case I want to extract hashmaps from sample5 whose "ckeydata" key has a vector which contains a hashmap having a "ckey" value of "test".

The data in Clojure format:

testdata {
    :sample1  "samplevalue1"
    :sample2  "samplevalue2"
    :sample3  {:innersample3  "innersamplevalue3"}
    :sample4  "samplevalue4"
    :sample5  [{:moresample [] 
               :link {innersample5  "innersamplevalue5"} 
               :ckeydata [{:ckey:"test" :something: somethingValue something2 somethingValue2}]}
               {:moresample [] 
                :link {innersample5  "innersamplevalue5"} 
                :ckeydata [{:ckey "test1" :something "somethingValue" :something2 "somethingValue2"}]}
               {:moresample [] 
                :link {:innersample5  "innersamplevalue5"} 
                :ckeydata [ {:ckey "test2" :something "somethingValue" :something2 "somethingValue2"}]}
               {:moresample [] 
                :link {innersample5 : "innersamplevalue5"} 
                :ckeydata [ {:ckey "test" :something  "somethingValue" :something2 "somethingValue2"}]}]}

Note: I don't want to use many filters and keep looping through the code.

Upvotes: 0

Views: 78

Answers (1)

xsc
xsc

Reputation: 6073

This should work:

(filter
  (fn [{:keys [ckeydata]}]
    (some (comp #{"test"} :ckey) ckeydata))
  (:sample5 testdata))

Which is a rather dense version of:

(filter
  (fn [sample-map]
    (some
      (fn [element]
        (= (:ckey element) "test"))
      (:ckeydata sample-map)))
  (:sample5 testdata))

If :ckeydata always only contains one element, consider:

(filter
  (comp #{"test"} :ckey first :ckeydata)
  (:sample5 testdata))

Upvotes: 3

Related Questions