Как я могу обновить векторный элемент в Clojure? - PullRequest
12 голосов
/ 25 февраля 2010

Дано:

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

Как можно идиоматически обновить * элемент в my-vec с :id=1, чтобы иметь значения :a="baz2" и :b="spam2"?

*: я признаю, что на самом деле я не буду обновлять my-vec, но действительно верну новый вектор, идентичный my-vec, за исключением значений замены.

Ответы [ 3 ]

10 голосов
/ 25 февраля 2010

Знаете ли вы заранее, что карта с 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. Тогда вам будет проще 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"}}
8 голосов
/ 25 февраля 2010

сопоставляет функцию с вектором карт, который либо создает измененную карту, если ключ соответствует, либо использует оригинал, если ключи не совпадают, затем преобразует результат обратно в вектор

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

Можно сделать это более кратко, хотя это действительно показывает, где происходит структурное разделение.

3 голосов
/ 05 марта 2010

Может быть, стоит взглянуть на массив-карту , которая создает карту с массивом и ключом индекса вместо использования: id?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...