2013-05-28 5 views
8

Я ищу что-то подобное select-keys:Есть ли стандартный func, который принимает dict и список ключей и возвращает список соответствующих vals?

(desired-fn {:a 1, :b 2, :c 3, :d 4} [:a :d]) 
;= [1 4] 

;; N.B. the order of the keys in the argument seq is preserved 
(= (desired-fn (array-map :a 1, :b 2, :c 3, :d 4) 
       [:b :c]) 
    (desired-fn (array-map :d 4, :c 3, :a 1, :b 2) 
       [:b :c])) 
;= true 

Это не особенно трудно осуществить, хотя я не пытался придумать хорошее название еще:

(defn select-values-corresponding-to-keys [m ks] 
    (for [k ks] 
    (get m k))) 

Am I не знающий стандартную функцию, которая отвечает именно этой потребности? Если нет, выполните другие языки - например, Python, Ruby, Haskell - есть имя для этой функции?

ответ

1

Jay Fields исследует эту функцию и пару других связанных с ними проницательных сообщений в блоге @http://blog.jayfields.com/2011/01/clojure-select-keys-select-values-and.html.

(я обнаружил, что случайно всего несколько минут назад, когда я искал «Select-ключи».)

я все же хотел бы знать, если есть «канонический» реализация где-то, так что я оставляя вопрос открытым.

+0

Как очевидно, существует «каноническая» реализация, и это «карта»; любой из приведенных выше ответов «карта» правильный. «map», используемый таким образом, является синонимом того, что статья Джей использует «select-values». –

10

Карты являются функциями, которые действуют на ключах:

({:a 1, :b 2} :a) 
;=> 1 

(map {:a 1, :b 2, :c 3, :d 4} [:a :d]) 
;=> (1 4) 

(= (map (array-map :a 1, :b 2, :c 3, :d 4) 
      [:b :c]) 
    (map (array-map :d 4, :c 3, :a 1, :b 2) 
      [:b :c])) 
;=> true 

Если вы хотите результат в виде вектора, просто использовать vec или into [] ... или замените map с mapv.

+3

другими словами (def wish-fn mapv) – noisesmith

+0

Вы абсолютно правы, что изящная функция Clojure означает, что функция тривиальна для реализации. (когда у меня возникла необходимость в 'select-values-matching-to-keys', я действительно решил сделать что-то очень похожее.) –

3

Ключевые слова сами по себе являются функции (они реализуют IFn), и они могут выглядеть сами в карту и возвращает значение, так один из вариантов было бы использовать juxt:

(def keys-to-vals (juxt :b :c)) 
(= (keys-to-vals {:a 1, :b 2, :c 3, :d 4}) 
    (keys-to-vals {:d 4, :c 3, :a 1, :b 2})) 

Так в основном нужная сноска теперь становится :

(defn select-vals [map keys] ((apply juxt keys) map)) 
3

map это функция, которую вы ищете:

(map {:a 1 :b 2 :c 3} [:a :c]) 
=> (1 3) 

Это работает, потому что сам хешмап работает как функция (т. реализует clojure.lang.IFn), который возвращает значение для любого ключа, который он задает.

3
user=> ((juxt :a :c) {:a 1 :b 2 :c 3}) 
[1 3] 
Смежные вопросы