S.H.
S.H.

Reputation: 211

Clojure- filter complex vector

I have been trying to filter complex vector like that

(def mySymbolT [[:name "salary" :type "string" :kind "static" :index 0]
  [:name "money" :type "string" :kind "static" :index 1] 
  [:name "count" :type "int" :kind "field" :index 0]])

My goal is to return the quantity of elements that has the same kind: For example, for kind "static" I expect 2 as an answer. So far I got to write this:

(defn countKind [symbolTable kind]
  (count(map first(filter #(= (:kind %) kind) symbolTable))))

Its not working. I must say that I'm new to Clojure and I dont understand well how filter goes with map, so I will be glad to hear explanations. (Yes, I have read the documentation about map and filter, still explanations missing for me, especially when I try to apply to large vectors.)

Upvotes: 0

Views: 260

Answers (2)

leetwinski
leetwinski

Reputation: 17849

@Thumbnail is right, it is better to rearrange the form of your data. But in case it comes from elsewhere and you just need to get some data from it several times (especially when the inner lists are quite short: theoretically it is even faster than to convert each one to map and lookup the key), you can avoid converting it into vector of maps like this:

first you can make a function to get property value by name from the vector:

(defn plist-get [look-for items]
  (when (seq items)
    (if (= look-for (first items))
      (second items)
      (recur look-for (drop 2 items)))))

and then just use it to get your result:

user> (def data [[:name "salary" :type "string" :kind "static" :index 0]
                 [:name "money" :type "string" :kind "static" :index 1] 
                 [:name "count" :type "int" :kind "field" :index 0]])
#'user/data

user> (count (filter #(= "static" (plist-get :kind %)) data))
;;=> 2

Upvotes: 1

Thumbnail
Thumbnail

Reputation: 13483

Your data would be better expressed as an array of maps than of vectors:

(def your-table [{:name "salary", :type "string", :kind "static", :index 0}
                 {:name "money", :type "string", :kind "static", :index 1} 
                 {:name "count", :type "int", :kind "field", :index 0}])

You can get there from here by ...

(def your-table
  (mapv (partial apply array-map) mySymbolT))

Now we can

  • use the keyword :kind as a function to extract those values, and
  • the core function frequencies to return what you ask.

For example ...

(frequencies (map :kind your-table))
;{"static" 2, "field" 1}

By the way, the Clojure idiom is to hyphenate words in a symbol: my-symbol-t instead of mySymbolT.

Upvotes: 4

Related Questions