2010-07-23 18 views
14

Dire che ho:Come faccio a moltiplicare tutti gli elementi in una raccolta con tutti gli elementi in un'altra raccolta?

(def s1 [1 2 3 4 5]) 
(def s2 [1 2 3 4 5]) 

Per ogni x in s1, voglio moltiplicarlo con ogni y in s2.


Per chiarire, io fondamentalmente voglio il prodotto cartesiano, quindi non credo map opere qui.

+1

Solo per divertimento, ecco alcune soluzioni in altre lingue. Erlang (e qualsiasi altra lingua con la comprensione delle liste): '[X * Y || X <- S1, Y <- S2] 'Ruby (1.8.7+):' s1.product (s2) .map {| x, y | x * y} ' –

risposta

22
(for [x1 s1 
     x2 s2] 
    (* x1 x2)) 
+11

È ... bello. * sheds a tear * –

+0

Sono molto nuovo a Clojure, e la programmazione funzionale in generale, anche se so cosa fa ... mi sembra ancora imbarazzante e difficile avvolgerla. Puoi descrivere cosa sta succedendo lì? –

+3

In primo luogo, è possibile digitare '(doc for)' in un REPL Clojure per ottenere una (si spera) una buona descrizione di cosa 'for' fa; se trovi che ti mancano le tue aspettative, la tua esperienza potrebbe aiutarti a migliorare la docstring! In secondo luogo, ecco un breve riassunto: 'for' prende un vettore vincolante e una singola espressione" corpo ". Il vettore di associazione comprende i nomi dei locali ('x1' e' x2' in alto) e le espressioni che producono la sequenza ('s1' e' s2'). Il corpo viene valutato una volta per ogni tupla di elementi nel prodotto cartesiano del seq (qui ciascuno ('x1',' x2') nel prodotto di 's1' e' s2'). –

2

Ecco la Java 1.5 (o più recente) l'equivalente di codice di Michal:

List<Integer> numbers = new ArrayList<Integer>();  

for(int x1 : s1) { 
    for(int x2 : s2) { 
    numbers.add(x1 * x2); 
    } 
} 

La differenza è che for loop in Java non restituiscono una sequenza come fanno in clojure, in modo da è necessario utilizzare un mutabile ArrayList per costruire il risultato.

Decisamente non bello come la versione clojure, ma molto meglio di quello che avresti dovuto fare in Java 1.4.

+1

Ma ancora..clojure;) – blushrt

2

Un semplice, dimostrazione visiva della funzionalità di base di for:

user=> (pprint 
     (for [tens (range 10) 
       ones (range 10)] 
      [tens ones])) 
([0 0] 
[0 1] 
[0 2] 
[0 3] 
[0 4] 
[0 5] 
[0 6] 
[0 7] 
[0 8] 
[0 9] 
[1 0] 
[1 1] 
[1 2] 
[1 3] 
[1 4] 
[1 5] 
[1 6] 
[1 7] 
[1 8] 
[1 9] 
[2 0] 
[2 1] 
[2 2] 
[2 3] 
[2 4] 
[2 5] 
[2 6] 
[2 7] 
[2 8] 
[2 9] 
[3 0] 
[3 1] 
[3 2] 
[3 3] 
[3 4] 
[3 5] 
[3 6] 
[3 7] 
[3 8] 
[3 9] 
[4 0] 
[4 1] 
[4 2] 
[4 3] 
[4 4] 
[4 5] 
[4 6] 
[4 7] 
[4 8] 
[4 9] 
[5 0] 
[5 1] 
[5 2] 
[5 3] 
[5 4] 
[5 5] 
[5 6] 
[5 7] 
[5 8] 
[5 9] 
[6 0] 
[6 1] 
[6 2] 
[6 3] 
[6 4] 
[6 5] 
[6 6] 
[6 7] 
[6 8] 
[6 9] 
[7 0] 
[7 1] 
[7 2] 
[7 3] 
[7 4] 
[7 5] 
[7 6] 
[7 7] 
[7 8] 
[7 9] 
[8 0] 
[8 1] 
[8 2] 
[8 3] 
[8 4] 
[8 5] 
[8 6] 
[8 7] 
[8 8] 
[8 9] 
[9 0] 
[9 1] 
[9 2] 
[9 3] 
[9 4] 
[9 5] 
[9 6] 
[9 7] 
[9 8] 
[9 9]) 
4

Mentre soluzione utilizzando per è più bello, ecco un mappa versione -solo se avete problemi di comprensione per:

(map #(map (partial * %) s2) s1) 

per sopra espande a qualcosa di simile, eccetto che sarebbe utilizzare un'altra funzione anonima anziché parziale, qualcosa di simile:

(map (fn [x] (map (fn [y] (* x y)) s2)) s1) 

o, ordinatamente formattato:

(map 
    (fn [x] 
    (map 
     (fn [y] 
     (* x y)) 
     s2)) 
    s1) 
+0

Voto positivo per l'alternativa. Mi chiedo se è più veloce. –

+0

BTW, per ottenere un comportamento identico a ** per ** la prima mappa (esterna) deve essere sostituita con mapcat. – dimagog

+0

@Blaine Guarda tu stesso :-): (usa 'clojure.pprint) (set-pprint-dispatch code-dispatch) (pprint (macroexpand' (per [x1 s1 x2 s2] (* x1 x2))))) – dimagog

1

semplice come si può ottenere:

(map * '(1 2) '(3 4)) 

produrrà:

(3 8) 
+0

Mmh ... non proprio quello che stavo cercando. Corrisponde alla mia descrizione inglese, ma avrei dovuto dire fin dall'inizio che stavo cercando il prodotto cartesiano di due set. Semplicemente non sapevo come si chiamava. –

+0

Oops, anzi, avrei dovuto preparare le risposte con più attenzione. – Jawher

Problemi correlati