简体   繁体   English

Clojure-计算地图键的值

[英]Clojure - calculating a value for a map key

I have a vector of maps. 我有地图矢量。 Each map has three keys :x, :y and :z. 每个地图都有三个键:x,:y和:z。 I want that the value of :z would be the sum of the values of keys :x and :y. 我希望:z的值是:x和:y的值的总和。 How should I do this? 我应该怎么做? ie

[{x: 5 :y 10 :z (+ :x :y)} {...} {...}]

In the above example, the first map's :z value should then be (+ 5 10) = 15. 在上面的示例中,第一个地图的:z值应为(+ 5 10)= 15。

Thanks for helping! 感谢您的帮助!

If you want to add those keys afterwards, you have to look at how to manipulate maps. 如果要在以后添加这些键,则必须查看如何操作地图。 In this case eg Destructuring and assoc are fine: 在这种情况下,例如Destructuring和assoc就可以了:

user=> (def m {:x 42 :y 666})
#'user/m
user=> (let [{:keys [x y]} m] (assoc m :z (+ x y)))
{:x 42, :y 666, :z 708}

Or if you want to create new maps with just the coords write a function for that 或者,如果您想仅使用坐标来创建新地图,请为此编写一个函数

user=> (defn coord [x y] {:x x :y y :z (+ x y)})
#'user/coord
user=> (coord 42 666)
{:x 42, :y 666, :z 708}
  • You can call assoc to set a value under a key in a map. 您可以调用assoc在地图中的键下设置值。 Note that most Clojure data structures are immutable so you can not alter the existing values but create modified copies. 请注意,大多数Clojure数据结构都是不可变的,因此您不能更改现有值,但可以创建修改后的副本。
  • You can call map or mapv functions or the for macro to iterate over a collection. 您可以调用mapmapv函数或for宏来遍历集合。 map and for will return a lazy sequence and mapv will return a vector. mapfor将返回延迟序列,而mapv将返回向量。

A simple solution: 一个简单的解决方案:

;; first we define the data
(def ms [{x: 5 :y 10} {:x 1 :y 1} {:x 2 :y 3}])

;; then we define a function that creates mutated data
(defn add-sum [ms] (mapv (fn [m] (assoc m :z (+ (:x m) (:y m)))) ms))

Alternatively with for macro: 或者使用for宏:

(defn add-sum [ms] (for [m ms] (assoc m :z (+ (:x m) (:y m)))))

Or with destructuring : 或具有破坏性

(defn add-sum [ms] (for [{:keys [x y]} ms] (assoc m :z (+ x y))))

It may help to parameterize this logic by extracting it out into a function if you plan on repeatedly doing this, although I would just create the :z key at the time you create the map, since you will presumably have access to x and y at that time. 如果您打算重复执行此操作,则可以通过将其提取到函数中来参数化此逻辑,尽管我会在创建映射时创建:z键,因为您可能会访问xy那时。

Barring that, here is an alterative to the fine solutions presented already, just generalized for different arguments. 除非这是已经提出的优良解决方案的替代方案,只是针对不同的论点进行了概括。

(def ms  [{:x 5 :y 10} {:x 5 :y 12} {:x 8 :y 10}])

(defn assoc-from-existing [m k & ks]
  (assoc m k (->> (select-keys m ks) vals (apply +))))

(mapv #(assoc-from-existing % :z :x :y) ms)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM