Clojure-过滤复杂向量

时间:2017-01-25 03:07:54

标签: dictionary vector filter clojure

我一直试图像那样过滤复杂的矢量

(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的新手,我不太清楚滤镜是如何与地图一起使用的,所以我很乐意听到解释。 (是的,我已经阅读了有关地图和过滤器的文档,但仍然缺少解释,特别是当我尝试应用于大型向量时。)

2 个答案:

答案 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