我一直试图像那样过滤复杂的矢量
(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]])
我的目标是返回具有相同种类的元素数量: 例如,对于类型“静态”我期望2作为答案。 到目前为止,我得写这个:
(defn countKind [symbolTable kind]
(count(map first(filter #(= (:kind %) kind) symbolTable))))
它不起作用。我必须说我是Clojure的新手,我不太清楚滤镜是如何与地图一起使用的,所以我很乐意听到解释。 (是的,我已经阅读了有关地图和过滤器的文档,但仍然缺少解释,特别是当我尝试应用于大型向量时。)
答案 0 :(得分:4)
您的数据将更好地表示为地图数组而非向量:
(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}])
你可以从这里到达那里......
(def your-table
(mapv (partial apply array-map) mySymbolT))
现在我们可以
:kind
作为提取这些值的函数,frequencies
返回您的要求。例如......
(frequencies (map :kind your-table))
;{"static" 2, "field" 1}
顺便说一句,Clojure成语是用符号连字:my-symbol-t
而不是mySymbolT
。
答案 1 :(得分:1)
@Thumbnail是对的,最好重新排列数据的形式。但是如果它来自其他地方并且您只需要从中获取一些数据(特别是当内部列表非常短时:理论上它甚至比将每个数据转换为映射和查找键更快),您可以避免将它转换为这样的地图矢量:
首先你可以创建一个函数来从vector中按名称获取属性值:
(defn plist-get [look-for items]
(when (seq items)
(if (= look-for (first items))
(second items)
(recur look-for (drop 2 items)))))
然后使用它来获得结果:
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