我有一张地图列表
( {:path "first" :size "1 gb"}
{:path "second" :size "500 mb"}
...)
和另一个地图列表
( {:path "first" :size "1 gb" :date "1"}
{:path "second" :size "500 mb" :date "1"}
{:path "first" :size "0.9 gb" :date "2"}...
{:path "second" :size "400 mb" :date "2"}...
...)
我希望将第一个地图列表转换为类似
的地图( {:path "first" :sizeon1 "1 gb" :sizeon2 "0.9 gb"...}
{:path "second" :sizeon1 "500 mb" :sizeon2 "400 mb"...}
....)
我是一个Clojure菜鸟,并且很难做到这一点。 你能帮帮我吗?
答案 0 :(得分:2)
当你将任务分解成更小的部分时,一切都变得清晰。
首先,定义一个帮助程序,在结果数据集中创建:sizeon1
个键:
(defn date-key
[date]
(keyword (str "sizeon" date)))
接下来,您希望将单个路径数据的集合减少为聚合映射,假设这样的集合看起来如您所述:
[{:path "first" :size "1 gb" :date "1"}
{:path "first" :size "0.9 gb" :date "2"}
;; ...
]
reduce
只是其中的工具:
(defn reduce-path
[path-data]
(reduce
;; A function that takes an accumulator map and an element in the collection
;; from which you take date and size and assoc them under the appropriate keys
(fn [acc el]
(let [{:keys [date size]} el]
(assoc acc (date-key date) size)))
;; A starting value for the accumulator containing the common path
;; for this collection
{:path (:path (first path-data))}
;; The collection of single path data to reduce
path-data))
最后,获取包含不同路径的原始数据集,按路径对其进行分区,并将reduce-path
函数映射到其上。
(def data
[{:path "first" :size "1 gb" :date "1"}
{:path "first" :size "0.9 gb" :date "2"}
{:path "second" :size "500 mb" :date "1"}
{:path "second" :size "400 mb" :date "2"}])
(->> data
(partition-by :path)
(map reduce-path))
请注意,此代码假定您的初始data
集合已按:path
排序。否则,partition-by
将无法正常工作,并且必须相应地准备数据。
答案 1 :(得分:2)
(def data '({:path "first" :size "1 gb" :date "1"}
{:path "second" :size "500 mb" :date "1"}
{:path "first" :size "0.9 gb" :date "2"}
{:path "second" :size "400 mb" :date "2"}))
(defn- reduce-group [g]
(reduce (fn [acc m] (assoc acc
(keyword (str "sizeon" (:date m)))
(:size m)))
(first g) g))
(let [groups (group-by :path data)]
(map reduce-group (vals groups)))
答案 2 :(得分:2)
我该怎么做,是重新考虑结果数据结构:
我不知道您将如何使用生成的集合,但命名密钥:sizeonX
,尤其是当可能存在可变数量的注册日期或者可能缺少其中一些时(例如,如果您有日期{第一条路径为{1}}和1
,第二条路径为3
1
2
3
,导致一系列不可预测的命名密钥地图,这将使得检索这些密钥变得更加困难。
对我而言,使用这种结构似乎更好:
5
所以这个尺寸图很容易迭代和处理。
我将如何做到这一点:
{:path "first" :sizes {"1" "500" "2" "1g" "10" "222"}}
<强>更新强>
但是你仍然需要问题的结构,我会这样做:
(def data '({:path "first" :size "1 gb" :date "1"}
{:path "first" :size "0.9 gb" :date "3"}
{:path "second" :size "500 mb" :date "1"}
{:path "second" :size "700 mb" :date "2"}
{:path "second" :size "400 mb" :date "3"}
{:path "second" :size "900 mb" :date "5"}))
(map (fn [[k v]] {:path k
:sizes (into {} (map (juxt :date :size) v))})
(group-by :path data))
;; ({:path "first", :sizes {"1" "1 gb", "3" "0.9 gb"}}
;; {:path "second", :sizes {"1" "500 mb",
;; "2" "700 mb",
;; "3" "400 mb",
;; "5" "900 mb"}})
基本上类似于@superkonduktr变种。