2012-02-20 9 views
5

Ho una funzione che desidera estrarre un valore da una mappa in base a un ordine prioritario. Attualmente lo sto facendo come struttura annidata se è orribile. Devo credere che ci sia un modo migliore.Clojure che estrae il valore dalla mappa in base alla logica prioritaria

Mentre questo funziona c'è un modo migliore?

(defn filter-relatives [relatives] 
    (if(contains? relatives :self) 
     (relatives :self) 
      (if(contains? relatives :north) 
       (relatives :north) 
        (if(contains? relatives :west) 
         (relatives :west) 
         (if(contains? relatives :east) 
          (relatives :east) 
          (relatives :south) 
         ) 
        ) 
       ) 
      ) 
     ) 
    ) 
) 

risposta

9
(some relatives [:self :north :west :east :south]) 
+1

Questa è la risposta corretta. –

+1

... a meno che non si voglia anche recuperare valori nulli. –

+3

... o 'false'. Se si tratta di un problema, vedi la mia risposta per un adeguamento appropriato, altrimenti usa decisamente questo. –

5

Che dire:

(defn filter-relatives [relatives ordered-filters] 
    (first (filter identity (map relatives ordered-filters)))) 

esempio di esecuzione:

user=> (filter-relatives {:a 1 :b 2 :c 3} [:z :b :a])                
2 
5

Le altre risposte vanno bene se nil e false non sono tra i possibili valori. Se lo sono, puoi usare qualcosa come

(if-let [e (some (partial find relatives) 
       [:self :north :west :east :south])] 
    (val e) 
    :no-key-found) 

E.g.

(if-let [e (some (partial find relatives) 
       [:self :north :west :east :south])] 
    (val e) 
    :no-key-found) 
; => false 

(if-let [e (some (partial find {}) 
       [:self :north :west :east :south])] 
    (val e) 
    :no-key-found) 
; => :no-key-found 
1
(first (keep relatives [:self :north :west :east :south]))