2010-07-23 3 views
14

Dire que j'ai:Comment puis-je multiplier tous les éléments d'une collection avec tous les éléments d'une autre collection?

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

Pour chaque x à s1, je veux multiplier avec tous les y en s2.


Pour clarifier les choses, je veux essentiellement le produit cartésien, donc je ne pense pas map œuvres ici.

+1

Juste pour le plaisir, voici quelques solutions dans d'autres langues. Erlang (et tout autre langage avec des compréhensions de liste): '[X * Y || X <- S1, Y <- S2] 'Ruby (1.8.7+):' s1.product (s2) .map {| x, y | x * y} ' –

Répondre

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

C'est ... beau. * jette une larme * –

+0

Je suis très nouveau à Clojure, et la programmation fonctionnelle en général, même si je sais ce que cela fait ... il me semble toujours difficile et difficile d'envelopper ma tête autour d'elle. Pouvez-vous décrire ce qui se passe là-bas? –

+3

Tout d'abord, vous pouvez taper '(doc pour)' sur une REPL Clojure pour obtenir une description (espérons-le) de ce que 'for' fait; Si vous trouvez qu'il est en deçà de vos attentes, votre expérience pourrait aider à améliorer la docstring! Deuxièmement, voici un bref résumé: 'for' prend un vecteur de liaison et une seule expression" body ". Le vecteur de liaison comprend des noms de locals («x1» et «x2» dans le tableau ci-dessus) et des expressions produisant une séquence («s1» et «s2»). Le corps est évalué une fois pour chaque tuple d'items dans le produit cartésien des seqs (ici chacun ('x1',' x2') dans le produit de 's1' et' s2'). –

2

est ici l'équivalent Java 1.5 (ou plus récent) du code de Michal:

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

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

La différence est que for boucles en java ne renvoient pas une séquence comme ils le font dans Clojure, de sorte que vous besoin d'utiliser un ArrayList mutable pour construire le résultat.

Certainement pas aussi joli que la version clojure, mais beaucoup mieux que ce que vous auriez dû faire dans Java 1.4.

+1

Mais still..clojure;) – blushrt

2

Une démonstration simple, visuelle de la fonctionnalité de base 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

Alors que la solution en utilisant pour est plus agréable, voici une carte la version -seulement si vous avez des problèmes de compréhension pour:

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

pour ci-dessus étend à quelque chose de similaire, sauf qu'il utiliserait une autre fonction anonyme au lieu de partielle, quelque chose comme ceci:

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

ou, d'une manière ordonnée formated:

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

Upvote pour l'alternative. Je me demande si c'est plus rapide. –

+0

BTW, pour obtenir un comportement identique à ** pour ** la première carte (externe) doit être remplacée par mapcat. – dimagog

+0

@Blaine Voir par vous-même :-): (utiliser 'clojure.pprint) (set-pprint-dispatch code-expédition) (pprint (macroexpand' (pour [x1 s1 x2 s2] (* x1 x2))) – dimagog

1

Aussi simple que cela peut obtenir:

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

donnera:

(3 8) 
+0

Mmh ... pas tout à fait ce que je cherchais. Cela correspond à ma description en anglais, mais j'aurais dû dire dès le départ que je cherchais le produit cartésien de deux ensembles. Je ne savais pas comment ça s'appelait. –

+0

Oups, en effet, je devrais avoir préparé les réponses plus attentivement. – Jawher

Questions connexes