2013-05-28 10 views
8

Sto cercando qualcosa di simile a select-keys:Esiste una funzione standard che accetta un comando e un elenco di chiavi e restituisce l'elenco dei valori corrispondenti?

(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 

Non è particolarmente difficile da attuare, anche se non ho provato a venire con un buon nome ancora:

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

Am I ignorante di una funzione standard che soddisfa proprio questa esigenza? In caso contrario, altri linguaggi, ad es. Python, Ruby, Haskell, hanno un nome per questa funzione?

risposta

1

Jay Fields esplora questa funzione e un paio di altri relativi in ​​un post del blog intuitivo @http://blog.jayfields.com/2011/01/clojure-select-keys-select-values-and.html.

(ho scoperto che per caso a pochi minuti fa, quando ho cercato per "selezionare-keys".)

mi piace ancora di sapere se c'è un'implementazione "canonica" da qualche parte, quindi sono lasciando la domanda come aperta.

+0

Come è probabilmente chiaro, esiste un'implementazione "canonica" ed è 'mappa'; una delle risposte di 'map' sopra sono corrette. 'map' usato in questo modo è un sinonimo di ciò che l'articolo di Jay chiama' select-values'. –

10

mappe sono funzioni che operano sulle loro chiavi:

({: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 

Se si desidera che il risultato come un vettore, basta usare vec o into [] ..., o sostituire map con mapv.

+3

in altre parole (def desiderato-fn mapv) – noisesmith

+0

Hai perfettamente ragione che un'elegante funzionalità di Clojure significa che la funzione è banale da implementare. (quando ho avuto bisogno di "select-values-correspondent-to-keys", ho deciso di fare qualcosa di molto simile). –

3

Le parole chiave sono essi stessi funzioni (implementano IFn) e possono guardano se stessi in una mappa e restituiscono il valore così una possibilità potrebbe essere quella di utilizzare 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})) 

Quindi, in pratica il tuo fn desiderato diventa ora :

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

map è la funzione che si sta cercando:

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

Questo funziona perché la stessa hashmap funziona come una funzione (ad es. implementa clojure.lang.IFn) che restituisce il valore per qualsiasi chiave che viene fornita.

3
user=> ((juxt :a :c) {:a 1 :b 2 :c 3}) 
[1 3] 
Problemi correlati