Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从clojure中的另一个映射列表向映射列表中的映射添加键值对_Clojure_Clojure Java Interop_Clojure Contrib - Fatal编程技术网

从clojure中的另一个映射列表向映射列表中的映射添加键值对

从clojure中的另一个映射列表向映射列表中的映射添加键值对,clojure,clojure-java-interop,clojure-contrib,Clojure,Clojure Java Interop,Clojure Contrib,我有一张地图清单 ( {: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

我有一张地图清单

 ( {: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" :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 noob,很难做到这一点。
你能帮帮我吗?

当你把任务分解成更小的部分时,一切都变得清晰了

首先,定义一个帮助器以在结果数据集中创建那些
: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))

请注意,此代码假定初始
数据
集合已按
:path
排序。否则,按划分的
将无法像您预期的那样工作,并且必须相应地准备数据。

当您将任务分解为更小的部分时,一切都变得清晰起来

(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)))
首先,定义一个帮助器以在结果数据集中创建那些
: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))

请注意,此代码假定初始
数据
集合已按
:path
排序。否则,按
划分的
将无法像您预期的那样工作,并且必须相应地准备数据。

我要做的是重新考虑生成的数据结构:
(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)))
我不知道您可能会如何使用生成的集合,但命名键
:sizeonX
,尤其是在注册日期数量可能可变或其中某些日期缺失的情况下(例如,如果第一条路径的日期为
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"}})
更新

但由于您仍然需要问题的结构,我会这样做:

(map (fn [[k v]]
       (into {:path k}
             (map #(vector (keyword (str "sizeon" (:date %)))
                           (:size %))
              v)))
     (group-by :path data))

;;({:path "first", :sizeon1 "1 gb", :sizeon3 "0.9 gb"} 
;; {:path "second", 
;;  :sizeon1 "500 mb", :sizeon2 "700 mb", 
;;  :sizeon3 "400 mb", :sizeon5 "900 mb"})

基本上与@superkonduktr variant相似。

我要做的是重新考虑生成的数据结构: 我不知道您可能会如何使用生成的集合,但命名键
:sizeonX
,尤其是在注册日期数量可能可变或其中某些日期缺失的情况下(例如,如果第一条路径的日期为
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"}})
更新

但由于您仍然需要问题的结构,我会这样做:

(map (fn [[k v]]
       (into {:path k}
             (map #(vector (keyword (str "sizeon" (:date %)))
                           (:size %))
              v)))
     (group-by :path data))

;;({:path "first", :sizeon1 "1 gb", :sizeon3 "0.9 gb"} 
;; {:path "second", 
;;  :sizeon1 "500 mb", :sizeon2 "700 mb", 
;;  :sizeon3 "400 mb", :sizeon5 "900 mb"})

这基本上与@superkonduktr variant相似。

非常感谢!正如您所说,如果集合不按:path排序,则按分区将不起作用。我的数据是这样的:所有地图都先显示:date“1”,然后显示:date“2”,依此类推……您能告诉我在这种情况下该怎么办吗?在这种情况下,您应该替换
(按:path分区)
行有两行:
(group by:path)
VAL
。这与
group by
将项目分组到一个映射中具有相同的效果,其中的值是类似于
分区结果的集合。
除了@leetwinski的建议之外,值得一提的是,您的数据缺少一个合理的(理想情况下是数字的)值要对其执行排序的字段。然后可以使用
(排序依据:可排序键集合)
在将集合提供给缩减函数之前,请确保正确的顺序。有关一些用法示例,请参阅!我已使用排序方式为该函数创建了一个函数。非常感谢!正如您所说,如果集合未按:路径排序,则分区方式将不起作用。我的数据是这样的:所有地图首先显示:date“1”,然后显示:date“2”诸如此类……您能告诉我在这种情况下该怎么办吗?在这种情况下,您应该将
(分区依据:路径)
行替换为两行:
(分组依据:路径)
VAL
。这与
分组方式
将项目分组到地图中的效果相同,其中的值是类似于
分区方式
结果的集合除了@leetwinski的建议之外,值得一提的是,您的数据缺少一个合理的(理想情况下是数字)字段来执行排序。然后您可以使用
(sort by:sortable key collection)
以确保在将集合提供给Reduced函数之前的顺序正确。有关一些用法示例,请参阅!我使用sort by为该函数创建了一个函数。我猜这是错误的,因为op可能希望根据键的
:date
值命名键(可能会有更多。(
:size3
等)我猜这是错误的,因为op可能想根据键的
:date
值命名键(可能会有更多。
:size3
等)在您的示例中,您并不真正需要第一个列表,因为它的数据在第二个列表中重复。它总是正确的,还是存在某些路径值的情况