Clojure:地图中的聚合和计数 [英] Clojure: Aggregate and Count in Maps

查看:120
本文介绍了Clojure:地图中的聚合和计数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我猜这个问题有资格作为一个入门级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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆