How to filter vector of maps by multiple keys in Clojure

后端 未结 1 1233
感情败类
感情败类 2021-02-11 10:46

Assume we have a datastructure like this one:

(def data
     (atom [{:id 1 :first-name \"John1\" :last-name \"Dow1\" :age \"14\"}
            {:id 2 :first-name          


        
1条回答
  •  野趣味
    野趣味 (楼主)
    2021-02-11 11:26

    This can also be achieved with the help of functional composition, e.g. you can use every-pred function, which creates a function, checking if all the preds are truthy for its arguments, and use it to filter data. For example if you want to find all items with odd :id value having :last-name of "Dow1", "Dow2", or "Dow3" and :age starting with \3:

    user> (def data
      [{:id 1 :first-name "John1" :last-name "Dow1" :age "14"}
       {:id 2 :first-name "John2" :last-name "Dow2" :age "54"}
       {:id 3 :first-name "John3" :last-name "Dow3" :age "34"}
       {:id 4 :first-name "John4" :last-name "Dow4" :age "12"}
       {:id 5 :first-name "John5" :last-name "Dow5" :age "24"}])
    
    user> (filter (every-pred (comp odd? :id)
                              (comp #{"Dow1" "Dow2" "Dow3"} :last-name)
                              (comp #{\3} first :age))
                  data)
    
    ;;=> ({:id 3, :first-name "John3", :last-name "Dow3", :age "34"})
    

    another way to do it, is to use transducers:

    user> (sequence (comp (filter (comp odd? :id))
                          (filter (comp #{"Dow1" "Dow2" "Dow3"} :last-name)))
                    data)
    

    notice that the actual filtering would happen just once for every item, so it won't create any intermediate collections.

    Update

    According to your update you need to keep the value when any of the predicates is true, so you can use some function instead of every-pred:

    user> (filter #(some (fn [pred] (pred %))
                         [(comp odd? :id)
                          (comp #{"Dow1" "Dow2" "Dow4"} :last-name)
                          (comp (partial = \3) first :age)])
                  data)
    ;;=> ({:id 1, :first-name "John1", :last-name "Dow1", :age "14"} {:id 2, :first-name "John2", :last-name "Dow2", :age "54"} {:id 3, :first-name "John3", :last-name "Dow3", :age "34"} {:id 4, :first-name "John4", :last-name "Dow4", :age "12"} {:id 5, :first-name "John5", :last-name "Dow5", :age "24"})
    

    0 讨论(0)
提交回复
热议问题