2010-07-23 29 views
14

Decir que tengo:¿Cómo multiplico todos los elementos en una colección con todos los elementos en otra colección?

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

Por cada x en s1, quiero multiplica con cada y en s2.


Para aclarar, Básicamente quiero el producto cartesiano, por lo que no creo map trabajos aquí.

+1

Solo por diversión, aquí hay algunas soluciones en otros idiomas. Erlang (y cualquier otro idioma con listas de comprensión): '[X * Y || X <- S1, Y <- S2] 'Ruby (1.8.7+):' s1.product (s2) .map {| x, y | x * y} ' –

Respuesta

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

Es ... hermoso. * arroja una lágrima * –

+0

Soy nuevo en Clojure, y la programación funcional en general, aunque sé lo que hace ... todavía me resulta incómodo y difícil de entender. ¿Puedes describir lo que está pasando allí? –

+3

En primer lugar, puede escribir '(doc for)' en Clojure REPL para obtener una (con suerte) buena descripción de lo que 'for' hace; Si encuentra que no cumple con sus expectativas, ¡su experiencia podría ayudar a mejorar el docstring! En segundo lugar, aquí hay un breve resumen: 'for' toma un vector de enlace y una única expresión de" cuerpo ". El vector de enlace incluye nombres de locales ('x1' y' x2' en el anterior) y expresiones que producen secuencias ('s1' y' s2'). El cuerpo se evalúa una vez por cada tupla de elementos en el producto cartesiano de los seqs (aquí cada uno ('x1',' x2') en el producto de 's1' y' s2'). –

2

Aquí es el Java 1.5 (o superior) equivalente de código de Michal:

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

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

La diferencia es que for bucles en java no devuelven una secuencia como lo hacen en clojure, por lo que necesita usar un ArrayList mutable para construir el resultado.

Definitivamente no tan bonita como la versión clojure, pero mucho mejor de lo que habría tenido que hacer en Java 1.4.

+1

Pero aún así ... Clojure;) – blushrt

2

Una demostración sencilla, visual de la funcionalidad básica de 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

Mientras solución utilizando para es más agradable, aquí es un mapa versión -sólo si tiene problemas de comprensión para:

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

por encima amplía a algo similar, excepto que usaría otra función anónima en lugar de parcial, algo como esto:

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

o, perfectamente formateados:

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

Voto a favor de la alternativa. Me pregunto si es más rápido. –

+0

BTW, para obtener un comportamiento idéntico a ** para **, el primer mapa (externo) debe reemplazarse con mapcat. – dimagog

+0

@Blaine Vea usted mismo :-): (uso 'clojure.pprint) (set-pprint-despacho-código expedición) (pprint (macroexpand' (por [x1 x2 s1 s2] (x1 * x2)))) – dimagog

1

Tan simple como se puede conseguir:

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

producirá:

(3 8) 
+0

Mmh ... no es exactamente lo que estaba buscando. Coincide con mi descripción en inglés, pero debería haber dicho desde el principio que estaba buscando el producto cartesiano de dos conjuntos. Simplemente no sabía cómo se llamaba. –

+0

Vaya, de hecho, debería haber preparado las respuestas con más cuidado. – Jawher

Cuestiones relacionadas