2010-02-24 43 views
12

考虑:如何更新Clojure中的矢量项?

(def my-vec [{:id 0 :a "foo" :b "bar"} {:id 1 :a "baz" :b "spam"} 
      {:id 2 :a "qux" :b "fred"}]) 

我怎样才能惯用更新*在我-VEC与:id=1的项目有价值观:a="baz2":b="spam2"

*:我承认我实际上不会更新my-vec,但真的会返回一个与我的vec相同的新的向量,除了替换值。

回答

8

地图上地图的载体功能,要么创建,如果密钥匹配修改地图或利用原有如果密钥不匹配,那么把结果返回到一个向量

(vec (map #(if (= (:id %) 1) 
      (assoc % :a "baz2" :b "spam2") 
      %))) 

它可以更简洁地做到这一点,虽然这真的显示结构共享发生的地方。

+0

使用#(%)函数语法是否使这个不太清楚? – 2010-02-25 19:30:05

10

您是否知道提前使用id == 1的地图是您矢量中的第二张地图?如果是这样的:

user> (-> my-vec 
      (assoc-in [1 :a] "baz2") 
      (assoc-in [1 :b] "spam2")) 
[{:id 0, :a "foo", :b "bar"} {:id 1, :a "baz2", :b "spam2"} {:id 2, :a "qux", :b "fred"}] 

如果需要通过ID来访问你的数据很多,另一个想法是哈希映射的哈希键地图上:id更换您的哈希地图矢量。那么无论事物的顺序如何,你都可以更容易地assoc-in

user> (def new-my-vec (zipmap (map :id my-vec) my-vec)) 
#'user/new-my-vec 
user> new-my-vec 
{2 {:id 2, :a "qux", :b "fred"}, 1 {:id 1, :a "baz", :b "spam"}, 0 {:id 0, :a "foo", :b "bar"}} 
user> (-> new-my-vec 
      (assoc-in [1 :a] "baz2") 
      (assoc-in [1 :b] "spam2")) 
{2 {:id 2, :a "qux", :b "fred"}, 1 {:id 1, :a "baz2", :b "spam2"}, 0 {:id 0, :a "foo", :b "bar"}} 
+0

嗯。我将它存储在一个矢量中,因为我实际上所持有的是纸牌的ImageIcons,当我绘制时,矢量位置将作为z顺序起作用。 [{:id“8H”:image ImageIcon} ...]。但是我可能能够将它们存储在地图{{:id“8H”:z-order 2:image ImageIcon} ...}中,然后通过将它们按排序后的z顺序拉出来进行Graphics.draw。谢谢,Brian,你是一个Clojure怪物。 :) – scrotty 2010-02-25 04:11:52

+4

'(update-in my-vec [1] assoc:a“baz2”:b“spam2”)'看起来要干净得多。 – amalloy 2011-04-02 07:49:41

3

可能要看一看array-map它创建一个由数组支持,并通过该指数,而不是使用键控图:ID?