2010-12-31 9 views
6

Mam odwołanie do wektora [], do którego dodano mapy. Jeśli chcę zmienić wartość elementu mapy na podstawie dopasowania predykatów, jaki jest idiomatyczny sposób to zrobić?idiomatyczny sposób aktualizowania map pasujących do predykatów w wektorze

Na przykład ...

[ {id 1: Nazwa "Joe"} { : id 2: nazwa "Fred"} ]

I chcemy zaktualizować każdy identyfikator 2 do nazwy "Brian".

+0

patrz: http://stackoverflow.com/questions/2330281/how-can-i-update-a -vector-item-in-clojure –

Odpowiedz

5

Oto jeden ze sposobów:

(def people [ { :id 1 :name "Joe" } { :id 2 :name "Fred" } ]) 

(defn brian-converter [person] 
    (if (= 2 (:id person)) 
     (assoc person :name "Brian") 
     person)) 

(map brian-converter people) 
;;=> ({:id 1, :name "Joe"} {:id 2, :name "Brian"}) 

W zależności od tego, jak można oczekiwać wartości te zmiany, może wolisz coś bardziej elastyczne:

(defn create-converter [[key-to-match val-to-match] 
         key-to-replace val-to-replace] 
    (fn [person] 
    (if (= val-to-match (key-to-match person)) 
     (assoc person key-to-replace val-to-replace) 
     person))) 

(map (create-converter [:id 2] :name "Brian") people) 
;;=> ({:id 1, :name "Joe"} {:id 2, :name "Brian"}) 
(map (create-converter [:id 1] :name "Dude") people) 
;;=> ({:id 1, :name "Dude"} {:id 2, :name "Fred"}) 

wybór reprezentacji argument (wektor dla params wyszukiwania , rozwinięte argumenty dla zastępstw) w create-converter były dla mnie arbitralne; nie wiem, czy jest na to reguła.

3

Innym sposobem jest znalezienie indeks mapie, który chcesz zaktualizować, a następnie aktualizować tylko tę mapę [EDIT: to jest przy założeniu, że tylko chcesz zaktualizować pojedynczy element w wektorze]:

(def people [{:id 1 :name "Joe"} {:id 2 :name "Fred"}]) 

(defn vecmap-assoc-pred 
    [vm pred & kvs] 
    (let [i (some (fn [[i m]] (when (pred m) i)) 
       (map-indexed vector vm))] 
    (apply update-in vm [i] assoc kvs))) 

(vecmap-assoc-pred people #(= 2 (:id %)) :name "Brian") 

w tym konkretnym przypadku, to prawdopodobnie większy sens, aby korzystać z mapy ludzi, wprowadzonego przez ID:

(def people {1 {:id 1 :name "Joe"} 2 {:id 2 :name "Fred"}}) 
(assoc-in people [2 :name] "Brian") 
Powiązane problemy