2015-01-25 5 views
4

У меня есть вектор и карта. И хочу, чтобы заменить элемент вектора, если это ключ карты (замените ключ со значением)заменить вектор, используя карту в clojure

user=> (def v [:a :b :c :d]) 
#'user/v 
user=> (def m {:a :k, :c :q}) 
#'user/m 

user=> (reduce (fn[x y] (conj x (if (y m) (y m) y))) [] v) 
[:k :b :q :d] 

Есть ли лучший способ сделать это?

ответ

6

Поскольку ваши входы и выходы представляют собой коллекцию одинаковой длины, и элементы коллекции рассчитываются независимо, было бы проще и более идиоматично использовать map или mapv для векторного вывода.

(mapv (fn [x] (m x x)) 
     v) 

или просто

(mapv #(m % %) v) 

Обратите внимание, что (m x x) похож на (if (contains? m x) (m x) x).

+2

Небольшой коррекция: '(получить Mxx)' равно '(if (содержит? mx) (mx) x)' (см. '(get {: x nil}: x: x)'). Кроме того, вы можете сократить функцию до '# (m%%)', так как карты реализуют 'IFn' и могут быть напрямую использованы для поиска. – xsc

+2

Спасибо, я не знал, что хэш-карта как функция также имеет «не найденное» значение. – TheQuickBrownFox

+0

Функция hash-map as не имеет значения по умолчанию. Функция 'get' делает. –

1

replace делает именно то, что вы хотите:

user> (replace {:a :x :b :y} [:a :b :c :d :e :f]) 
[:x :y :c :d :e :f] 

Примечания он работает с векторами в ассоциативной коллекции, где ключи являются индексами:

user> (replace [:a :b :c :d] [0 2 4 3 2 1]) 
[:a :c 4 :d :c :b] 
Смежные вопросы