List Clojure:列出单个键的值

List Clojure:列出单个键的值,list,join,clojure,List,Join,Clojure,我来自Python世界,在那里很容易进行平均/分组。但我正在用clojure编程,我想从一个大的查询结果中计算每个文章ID的平均值 格式化查询结果后,我得到了类似的结果(这是一个示例,结果要大得多): 我想先有这样的想法: (“123”[233320]“234”[25]) 这就是想法,最终结果将是: ({:文章编号“123”:平均276.5}{:文章编号“234”:平均25}) 所以我需要两个步骤:列出值,然后应用均值函数。第二部分对我来说听起来不错,但我在第一步就被绊倒了:列出值 1) 方法1

我来自Python世界,在那里很容易进行平均/分组。但我正在用clojure编程,我想从一个大的查询结果中计算每个文章ID的平均值

格式化查询结果后,我得到了类似的结果(这是一个示例,结果要大得多):

我想先有这样的想法:

(“123”[233320]“234”[25])

这就是想法,最终结果将是:

({:文章编号“123”:平均276.5}{:文章编号“234”:平均25})

所以我需要两个步骤:列出值,然后应用均值函数。第二部分对我来说听起来不错,但我在第一步就被绊倒了:列出值

1) 方法1

我定义:

(defn list-column [query fields]
  (let [values (into {} (map (fn [x] {(x :Article_ID) []}) query))]
    (map clojure.walk/keywordize-keys
      (map (partial zipmap fields) values))))
推出:

(list-column sample ["Article_ID" "Values"])
所以我有

({:Article_ID "123" :Values []} {:Article_ID "234" :Values []} {:Article_ID "123" :Values []}
2) 方法2:

我也试过了

(defn list-column [query]
  (into {} (map (fn [x] {(x :Article_ID) []}) query)))
拥有:

("123" [] "234" [])
我现在只关注列表部分

1) 计算平均值的最佳方法是什么?不关心最终格式(可以更改) 2) 如何将每个价格附加到每个:值字段

我想我必须使用conj来追加。可能会关联ID匹配,但不知道如何将其组合在一起(不知道如何将第一个列表中的article_ID绑定到第二个列表中的值)

谢谢

编辑:

这是最后一个要重用的函数

(defn agg-mean-value [query key value]
  (let [init-list (->> (group-by key sample)
     (map (fn [[k v]]
              [k (mapv value v)]))
     (into {}))]
    (map (fn [[k vs]]
           {key k value (/ (reduce + vs) (count vs))})
         init-list)))
随着我知识的增长,我将在未来对其进行改进。Clojure的功能将完成我认为的第一部分

(group-by :Article_ID sample)
    => {"123" [{:Article_ID "123", :Price 233} {:Article_ID "123", :Price 320}], "234" [{:Article_ID "234", :Price 25}]}
您可以这样计算平均值:

(defn mean [vals]
    (/ (apply + vals) (count vals)))
我们可以通过以下方式清理该组:

(->> (group-by :Article_ID sample)
     (map (fn [[k v]]
              [k (mapv :Price v)]))
     (into {}))
=> {"123" [233 320], "234" [25]}
最后应用均值函数得出以下结果:

(->> (group-by :Article_ID sample)
     (map (fn [[k v]]
              [k (mapv :Price v)]))
     (into {})
     (vals)
     (map mean))

=> (553/2 25)

我通常更喜欢使用
reduce
对值进行分组。它的可读性可能会降低,但我可以更好地控制输出。关于这个具体问题,我承认你没有从使用
reduce
(与
groupby
相反)中获得太多的价值,但我想无论如何我都会发布

(def groups
  (reduce
    (fn [m {:keys [Article_ID Price]}]
      (assoc m Article_ID (conj (get m Article_ID []) Price)))
    {}
    sample))
这将为您提供键和向量的hashmap:

=> {"123" [233 320], "234" [25]}
从那里,您可以映射到您的组:

(map (fn [[k vs]]
       {:Article_ID k :Mean (/ (reduce + vs) (count vs))})
     groups)
并产生您想要的结果:

=> ({:Article_ID "123", :Mean 553/2} {:Article_ID "234", :Mean 25})

一般来说,在(可能未排序的)地图上首先使用
是个坏主意。您应该使用
(分组依据:Article\u ID sample)
。最后一个示例与
(>>(分组依据:Article\u ID-示例)(VAL(map#)(平均值(mapv:价格%))不一样吗
?看起来差不多。有很多方法可以解决这个问题。不过它可能有一些语法问题。非常感谢,效果很好。我正在探索该语言并尝试一些事情。不理解->>是如何工作的,但这里很清楚。也谢谢,我混合了这两种答案,为大型查询创建了一个可重用的通用函数s
=> ({:Article_ID "123", :Mean 553/2} {:Article_ID "234", :Mean 25})