Mise à jour 2020 : réponse d'une ligne ( !) avec vanilla JS
Réponse originale 2017 : réponse de 2 lignes avec vanilla JS : (voir les mises à jour ci-dessous)
Toutes les réponses ici sont trop compliqué la plupart d'entre elles nécessitent 20 lignes de code, voire plus.
Cet exemple n'utilise que deux lignes de vanilla JavaScript pas de lodash, underscore ou d'autres bibliothèques :
let f = (a, b) => [].concat(...a.map(a => b.map(b => [].concat(a, b))));
let cartesian = (a, b, ...c) => b ? cartesian(f(a, b), ...c) : a;
Mise à jour :
C'est la même chose que ci-dessus mais amélioré pour suivre strictement le Guide de style JavaScript d'Airbnb - validée en utilisant ESLint con eslint-config-airbnb-base :
const f = (a, b) => [].concat(...a.map(d => b.map(e => [].concat(d, e))));
const cartesian = (a, b, ...c) => (b ? cartesian(f(a, b), ...c) : a);
Remerciements particuliers à ZuBB pour m'avoir informé des problèmes de linter avec le code original.
Mise à jour 2020 :
Depuis que j'ai écrit cette réponse, nous avons obtenu des modules intégrés encore meilleurs, qui peuvent enfin nous permettre de réduire (sans jeu de mots) le code à une seule ligne !
const cartesian =
(...a) => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat())));
Remerciements particuliers à encreur pour avoir suggéré l'utilisation de reduce.
Remerciements particuliers à Bergi pour avoir suggéré l'utilisation de la flatMap nouvellement ajoutée.
Remerciements particuliers à ECMAScript 2019 pour avoir ajouté flat et flatMap au langage !
Exemple
C'est l'exemple exact de votre question :
let output = cartesian([1,2],[10,20],[100,200,300]);
Sortie
Voici le résultat de cette commande :
[ [ 1, 10, 100 ],
[ 1, 10, 200 ],
[ 1, 10, 300 ],
[ 1, 20, 100 ],
[ 1, 20, 200 ],
[ 1, 20, 300 ],
[ 2, 10, 100 ],
[ 2, 10, 200 ],
[ 2, 10, 300 ],
[ 2, 20, 100 ],
[ 2, 20, 200 ],
[ 2, 20, 300 ] ]
Démo
Voir les démos sur :
Syntaxe
La syntaxe que j'ai utilisée ici n'est pas nouvelle. Mon exemple utilise l'opérateur d'étalement et les paramètres de repos - des caractéristiques de JavaScript définies dans la 6e édition de la norme ECMA-262 publiée le juin 2015 et développée bien avant, plus connue sous le nom de ES6 ou ES2015. Voir :
Les nouvelles méthodes de l'exemple de la mise à jour 2020 ont été ajoutées dans ES2019 :
Il rend ce genre de code si simple que c'est un péché de ne pas l'utiliser. Pour les anciennes plateformes qui ne le supportent pas nativement, vous pouvez toujours utiliser Babel ou d'autres outils pour le transposer dans une syntaxe plus ancienne - et en fait, mon exemple transposé par Babel est toujours plus court et plus simple que la plupart des exemples ici, mais cela n'a pas vraiment d'importance parce que le résultat de la transpilation n'est pas quelque chose que vous devez comprendre ou maintenir, c'est juste un fait que j'ai trouvé intéressant.
Conclusion
Il n'est pas nécessaire d'écrire des centaines de lignes de code difficiles à maintenir et il n'est pas nécessaire d'utiliser des bibliothèques entières pour une chose aussi simple, quand deux lignes de vanilla JavaScript peuvent facilement faire le travail. Comme vous pouvez le constater, l'utilisation des fonctionnalités modernes du langage est vraiment rentable et dans les cas où vous devez prendre en charge des plates-formes archaïques sans support natif des fonctionnalités modernes, vous pouvez toujours utiliser Babel , TypeScript ou d'autres outils pour transpiler la nouvelle syntaxe vers l'ancienne.
Ne codez pas comme si on était en 1995
JavaScript évolue et il le fait pour une raison. Le CT39 fait un travail remarquable de conception du langage en ajoutant de nouvelles fonctionnalités et les fournisseurs de navigateurs font un travail remarquable de mise en œuvre de ces fonctionnalités.
Pour connaître l'état actuel de la prise en charge native d'une fonctionnalité donnée dans les navigateurs, voir :
Pour voir le support dans les versions de Node, voir :
Pour utiliser la syntaxe moderne sur des plateformes qui ne la prennent pas en charge de manière native, utilisez Babel ou TypeScript :