2010-02-24 5 views
12

을 감안할 때 :Clojure에서 벡터 항목을 업데이트하려면 어떻게해야합니까?

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

어떻게 관용구 :id=1 내-VEC의 항목이 :a="baz2":b="spam2"을 값을 가지고 * 업데이트 할 수 있습니다?

* : 나는 실제로 my-vec를 업데이트하지 않지만 대체 값을 제외하고는 my-vec와 동일한 새 벡터를 실제로 반환한다는 것을 알고 있습니다.

답변

8

지도 키와 일치하는 경우 수정 된 맵을 만들거나 키가 다음과 일치하는 벡터로 결과를 다시 설정하지 않는 경우 원본을 사용하거나지도의 벡터를 통해 기능

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

그것을 이것은 구조 공유가 일어나는 곳을 실제로 보여 주지만 더 간결하게 할 수 있습니다.

+0

# (%) 함수 구문을 사용하면이 사실이 명확하지 않습니까? –

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

흠. 내가 실제로 들고있는 것은 카드 놀이의 ImageIcon이고 벡터 위치는 내가 그릴 때 z-order로 작용하기 때문에 벡터에 저장합니다. [{: id "8H": 이미지 ImageIcon} ...]. 그러나지도 {{: id "8H": z-order 2 : Image ImageIcon} ...}에 저장 한 다음 Graphics.draw를 정렬 된 : z 순서로 끌어 와서 저장할 수 있습니다. 고마워요, 브라이언, 당신은 Clojure 괴물입니다. :) – scrotty

+4

'(update-in my-vec [1] assoc : a "baz2": b "spam2")'훨씬 더 깨끗해 보입니다. – amalloy

3

인덱스 대신 사용하여 배열에 근거하고 키가 맵을 생성 array-map에서 살펴 봐야 할 것인가?

관련 문제