我正在尝试使用 clojure map 了解一个简单的(如在其他语言中一样)工作流程。
基本上归结为:如何链接这些操作?
group-by
: map 向量上的键 select-keys
在没有前一个键的剩余 map 上 group-by
再次(0..n 次)并选择键 count
最后的唯一键实例。 另见我之前的问题:Aggregate and Count in Maps
示例:
给定一个 map 向量
(def DATA [{:a "X", :b "M", :c "K", :d 10}
{:a "Y", :b "M", :c "K", :d 20}
{:a "Y", :b "M", :c "F", :d 30}
{:a "Y", :b "P", :c "G", :d 40}])
执行
group-by
(defn get-tree-level-1 [] (group-by :a DATA))
生成按该特定键的值分组的映射。
{ X [{:a X, :b M, :c K, :d 10}],
Y [{:a Y, :b M, :c K, :d 20}
{:a Y, :b M, :c F, :d 30}
{:a Y, :b P, :c G, :d 40}]}
到现在为止还挺好。但是如果我想从数据中构建一个 树状结构 呢,这意味着选择剩余的键并忽略一些,选择
:b
和 :c
并忽略 :d
,这将在下一级别产生:(def DATA2 [{ :X [{:b "M", :c "K"}],
:Y [{:b "M", :c "K"}
{:b "M", :c "F"}
{:b "P", :c "G"}]}])
最后,计算剩余键的所有实例(例如,计算
:b
-root 下 Y
键的所有唯一值):(def DATA3 [{ :X [{:M 1}],
:Y [{:M 2}
{:P 1}])
我尝试在
select-keys
之后执行 group-by
,但第一步后结果为空:(defn get-proc-sums []
(into {}
(map
(fn [ [k vs] ]
[k (select-keys vs [:b :c])])
(group-by :a DATA))))
最佳答案
重复应用 group-by 是错误的工具:它不能很好地与自身组合。相反,检查您的输入映射并将它们中的每一个转换为对您有用的格式(使用 for
或 map
),然后减少它以构建树结构。这是一个简单的实现:
(defn hierarchy [keyseq xs]
(reduce (fn [m [ks x]]
(update-in m ks conj x))
{}
(for [x xs]
[(map x keyseq) (apply dissoc x keyseq)])))
user> (hierarchy [:a :b :c] '[{:a "X", :b "M", :c "K", :d 10}
{:a "Y", :b "M", :c "K", :d 20}
{:a "Y", :b "M", :c "F", :d 30}
{:a "Y", :b "P", :c "G", :d 40}])
{"Y" {"P" {"G" ({:d 40})},
"M" {"F" ({:d 30}),
"K" ({:d 20})}},
"X" {"M" {"K" ({:d 10})}}}
这为您提供了所需的分层格式,其中包含所有 map 的列表,其中仅包含“剩余”键。由此,您可以计算它们、区分它们、删除
:d
键或任何您想要的东西,方法是编写另一个处理此映射的函数,或者通过调整上面的 reduce 函数或 for
理解中发生的事情。关于Clojure:将 group-by :key 与剩余键上的选择键链接起来,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36183706/