2012-11-02 19 views
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的值,但是這只是一個例子。

+0

你能澄清一下'[[0 1] [0 1]]是什麼意思?它是由「(範圍2)」創建的兩個向量的向量嗎?或者是其他東西? –

+0

當然,對不起,不清楚。我只是希望它生成嵌套向量而不是嵌套地圖(或地圖向量)我將編輯我的問題 – user1782011

回答

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))) 

注意,它調用get上的if條件的真實分支。如果你想自己的使用向量,而不是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

是的,這是我想要的。感謝您的解釋。 – user1782011

+0

@ user1782011 - 很高興聽到它!如果這是您正在尋找的內容,那麼您可以接受我的回答,以表明此問題已得到解答。 – DaoWen

+1

做到了,最好遲到,永遠不要爲延遲抱歉 – user1782011

0

看來你需要的東西,如:

user=> (let [cv #(apply vector %)] 
     (cv (map cv (repeat 5 (range 2))))) 
[[0 1] [0 1] [0 1] [0 1] [0 1]] 
+1

'#(apply vector%)'只是'vec'。 – amalloy

相關問題