2

assoc-in 可以更改向量/映射中索引/键的值。在地图中,如果一个键不存在,那么它会创建一个新的键/值对。向量是否有类似的东西(如果索引不存在,它会在该索引处创建一个具有该值的列表)类似于:

 (reduce (fn [g [x y]] (assoc-in g [x y] y ))
        []
        (for [x (range 2) 
              y (range 2)]
             [x y]))

上面的代码生成:

[{1 1, 0 0} {1 1, 0 0}]

我希望它生成:

[[0 1] [0 1]]

这可能以简单的方式吗?

谢谢

编辑:为了更清楚,我只是希望它生成嵌套向量而不是嵌套映射(或映射向量)现在我将 y 作为一个值,但这只是一个例子。

4

2 回答 2

6

在一般情况下,创建向量而不是地图不会很好,因为您只能assoc在向量中使用现有索引或下一个索引:

user=> (assoc [:a] 0 :b) ; works because index 0 exists
[:b]
user=> (assoc [:a] 1 :b) ; works because index 1 is next
[:a :b]
user=> (assoc [:a] 2 :b) ; fails since index is out of range
IndexOutOfBoundsException   clojure.lang.PersistentVector.assocN (PersistentVector.java:136)

但是,如果你小心,你仍然可以让它工作。这是以下的实现assoc-in

(defn assoc-in
  [m [k & ks] v]
  (if ks
    (assoc m k (assoc-in (get m k) ks v))
    (assoc m k v)))

请注意,它调用getif条件的真实分支。如果您希望自己的版本assoc-in使用向量,则可以添加一个空向量作为返回的默认值get

(defn vassoc-in
  [m [k & ks] v]
  (if ks
    (assoc m k (vassoc-in (get m k []) ks v))
    (assoc m k v)))

在您的问题中使用vassoc-in而不是assoc-in在示例代码中会产生[[0 1] [0 1]]您想要的结果。

于 2012-11-02T15:46:43.760 回答
0

看来您需要类似的东西:

user=> (let [cv #(apply vector %)] 
         (cv (map cv (repeat 5 (range 2)))))
[[0 1] [0 1] [0 1] [0 1] [0 1]]
于 2012-11-02T15:32:11.217 回答