Clojure:地图中的聚合和计数 [英] Clojure: Aggregate and Count in Maps
问题描述
我猜这个问题有资格作为一个入门级clojure问题。我基本上有麻烦处理clojure地图多次,并提取不同种类的数据。
给定一个这样的地图,我试图基于多个嵌套键:
[
{
a:X,
b :M,
c:188
},
{
a:Y,
b:M b $ bc:165
},
{
a:Y,
b:M,
c :313
},
{
a:Y,
b:P,
c:188
}
]
首先,我要通过a键值对条目进行分组:
{
X:[
{
b:M ,
c:188
}
],
Y:[
{
b:M,
c:165
},
{
b:M,
c:313
},
{
b:P,
c:188
}
]
}
其次,我想假设b键的值是重复的,并忽略剩下的键:
{
X:[
{
b:M
}
],
Y :[
{
b:M
}
{
b:P
}
]然后,简单地对b-key的所有实例进行计数:
{
X:1,
Y:2
}
当我通过monger获取数据时,我定义:
(defn db-query
([coll-name]
(with-open [conn(mg / connect)]
(doall / find-maps(mg / get-db conn db-name)coll-name))))
然后点击路障:
(defn get-sums [request]
( - > (db-querydata)
(group-by:a)
(into {})
keys))
我如何从这里继续?
解决方案方法,我相信有更好的方法,但它可能是你需要找出来。
(into {}
(map
; f
(fn [[k vs]]; [k`unique count`]
[k #(get%b)vs)))])
; coll
(group-by#(get%a)DATA) as as keys
; user => {X1,Y2}
说明:
;我使用你的文字数据作为DATA,只是删除,和;
(def DATA [{...
(group-by#(get%a)DATA);按a分组为键
;地图{X:[{},...]Y:[{},{},{},...]}
] pair其中
; k是映射关键字和
; vs是向量中的分组映射
(fn [[k vs]]
;这里的k Y和`vs`是地图{a _,b,_,c _}
;现在`(map#(get%b)vs)值
;`into set`使它们成为
;`count`计数它们
;最后我返回一个同名为`k`,
的向量;计数的`b`s
[k(count(into#{}(map%(get%b)vs)))])
;结果`[[Y2] [X1]]``into`一个map {}
;所以你得到一个映射
I guess this question qualifies as an entry-level clojure problem. I basically have troubles processing a clojure map multiple times and extract different kinds of data.
Given a map like this, I'm trying to count entries based on multiple nested keys:
[
{
"a": "X",
"b": "M",
"c": 188
},
{
"a": "Y",
"b": "M",
"c": 165
},
{
"a": "Y",
"b": "M",
"c": 313
},
{
"a": "Y",
"b": "P",
"c": 188
}
]
First, I want to group the entries by the a-key values:
{
"X" : [
{
"b": "M",
"c": 188
}
],
"Y" : [
{
"b": "M",
"c": 165
},
{
"b": "M",
"c": 313
},
{
"b": "P",
"c": 188
}
]
}
Second, I want to assume values of b-keys as duplicates and ignore the remaining keys:
{
"X" : [
{
"b": "M"
}
],
"Y" : [
{
"b": "M"
}
{
"b": "P"
}
]
}
Then, simply count all instances of the b-key:
{
"X" : 1,
"Y" : 2
}
As I'm getting the data through monger, I defined:
(defn db-query
([coll-name]
(with-open [conn (mg/connect)]
(doall (mc/find-maps (mg/get-db conn db-name) coll-name))))
and then hitting the roadblock:
(defn get-sums [request]
(->> (db-query "data")
(group-by :a)
(into {})
keys))
How could I continue from here?
解决方案 This is a naive approach, I am sure there are better ways but it might be what you need to figure it out.
(into {}
(map
; f
(fn [ [k vs] ] ;[k `unique count`]
[k (count (into #{} (map #(get % "b") vs)))])
; coll
(group-by #(get % "a") DATA))) ; "a"s as keys
;user=> {"X" 1, "Y" 2}
Explanation:
; I am using your literal data as DATA, just removed the , and ;
(def DATA [{...
(group-by #(get % "a") DATA) ; groups by "a" as keys
; so I get a map {"X":[{},...] "Y":[{},{},{},...]}
; then I map over each [k v] pair where
; k is the map key and
; vs are the grouped maps in a vector
(fn [ [k vs] ]
; here `k` is e.g. "Y" and `vs` are the maps {a _, b, _, c _}
; now `(map #(get % "b") vs)` gets me all the b values
; `into set` makes them uniqe
; `count` counts them
; finally I return a vector with the same name `k`,
; but the value is the counted `b`s
[k (count (into #{} (map #(get % "b") vs)))])
; at the end I just put the result `[ ["Y" 2] ["X" 1] ]` `into` a map {}
; so you get a map
这篇关于Clojure:地图中的聚合和计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!