197 votes

Équivalent de JavaScript de Python ' fonction zip s

Y at-il un script javascript équivalent de la fonction zip de Python ? Autrement dit, compte tenu de deux tableaux de longueur égale créer un tableau de paires.

Par exemple, si j’ai trois baies qui ressemblent à ceci :

Le tableau de sortie doit être :

166voto

ninjagecko Points 25709

Voici un oneliner:

function zip(arrays) {
    return arrays[0].map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

// > zip([[1,2],[11,22],[111,222]])
// [[1,11,111],[2,22,222]]]

// If you believe the following is a valid return value:
//   > zip([])
//   []
// then you can special-case it, or just do
//  return arrays.length==0 ? [] : arrays[0].map(...)

Le ci-dessus suppose que les matrices sont de taille égale, comme ils devraient l'être. Cela suppose également de vous transmettre en une seule liste de listes argument, contrairement à python version où la liste d'arguments est variadic. Si vous voulez que tous ces "fonctionnalités", voir ci-dessous. Il faut à peu près 2 lignes de code supplémentaires.

La suivante va imiter python zip comportement sur le bord des cas où les tableaux ne sont pas de taille égale, silencieusement prétendant le plus de parties de tableaux n'existent pas:

function zip() {
    var args = [].slice.call(arguments);
    var shortest = args.length==0 ? [] : args.reduce(function(a,b){
        return a.length<b.length ? a : b
    });

    return shortest.map(function(_,i){
        return args.map(function(array){return array[i]})
    });
}

// > zip([1,2],[11,22],[111,222,333])
// [[1,11,111],[2,22,222]]]

// > zip()
// []

Ce sera imiter python itertools.zip_longest comportement, l'insertion d' undefined où les tableaux ne sont pas définis:

function zip() {
    var args = [].slice.call(arguments);
    var longest = args.reduce(function(a,b){
        return a.length>b.length ? a : b
    }, []);

    return longest.map(function(_,i){
        return args.map(function(array){return array[i]})
    });
}

// > zip([1,2],[11,22],[111,222,333])
// [[1,11,111],[2,22,222],[null,null,333]]

// > zip()
// []

Si vous utilisez ces deux dernières version (variadic aka. plusieurs arguments versions), puis zip n'est plus à son inverse. Pour imiter l' zip(*[...]) idiome de python, vous aurez besoin de faire zip.apply(this, [...]) lorsque vous voulez inverser le zip de la fonction ou si vous voulez de la même manière, un nombre variable de listes comme entrée.


addendum:

Pour faire cette poignée importe quel itérable (par exemple en python, vous pouvez utiliser zip sur les cordes, les gammes, les objets de la carte, etc.), vous pouvez définir les éléments suivants:

function iterView(iterable) {
    // returns an array equivalent to the iterable
}

Toutefois, si vous écrivez zip de la suivante façon, même cela ne sera pas nécessaire:

function zip(arrays) {
    return Array.apply(null,Array(arrays[0].length)).map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

Démo:

> JSON.stringify( zip(['abcde',[1,2,3,4,5]]) )
[["a",1],["b",2],["c",3],["d",4],["e",5]]

(Ou vous pouvez utiliser un range(...) python-style de la fonction, si vous avez écrit un déjà. Finalement, vous serez en mesure d'utiliser ECMAScript tableau des inclusions ou des générateurs.)

33voto

Brandon Points 1135

Découvrez la bibliothèque de Soulignement

"Trait de soulignement fournit 60-unes des fonctions qui prennent en charge à la fois l'habitude fonctionnelle suspects: carte, sélectionnez, appelez - ainsi que plus spécialisés aides: la fonction de liaison, javascript templating, profonde de l'égalité des tests, et ainsi de suite." - Que disent les gens qui l'ont fait!

J'ai récemment commencé à utiliser spécifiquement pour le zip de la fonction et il a laissé une bonne première impression. Je suis à l'aide de jQuery et CoffeeScript, et il va parfaitement avec eux. Trait de soulignement reprend là où ils s'arrêtent et jusqu'à présent cela n'a pas marché pour moi. Oh by the way, c'est seulement 3kb minied.

Check it out.

15voto

Lo Sauer Points 5469

En plus de ninjagecko excellente réponse complète et, tout ce qu'il faut pour zip deux JS-des tableaux dans un "tuple-d'imiter" est:

//Arrays: aIn, aOut
Array.prototype.map( aIn, function(e,i){return [e, aOut[i];]})

Explication:
Depuis Javascript n'est pas un tuples type, les fonctions de tuples, listes et les ensembles n'était pas une priorité lors de la spécification du langage.
Sinon, un comportement similaire est accessible de façon simple via la Matrice de carte en JS >1.6. (map est en fait souvent mis en œuvre par JS fabricants de moteur dans de nombreux >JS 1.4 moteurs, en dépit de ne pas spécifié).
La différence majeure à Python zip, izip,... les résultats de map's style fonctionnel, puisqu' map nécessite une fonction-argument. En outre, il est une fonction de l' Array-exemple. On peut utiliser Array.prototype.map au lieu de cela, si un supplément de déclaration pour l'entrée est un problème.

Exemple:

_tarrin = [0..constructor, function(){}, false, undefined, '', 100, 123.324,
         2343243243242343242354365476453654625345345, 'sdf23423dsfsdf',
         'sdf2324.234dfs','234,234fsf','100,100','100.100']
_parseInt = function(i){return parseInt(i);}
_tarrout = _tarrin.map(_parseInt)
_tarrin.map(function(e,i,a){return [e, _tarrout[i]]})

Résultat:

//'('+_tarrin.map(function(e,i,a){return [e, _tarrout[i]]}).join('),\n(')+')'
>>
(function Number() { [native code] },NaN),
(function (){},NaN),
(false,NaN),
(,NaN),
(,NaN),
(100,100),
(123.324,123),
(2.3432432432423434e+42,2),
(sdf23423dsfsdf,NaN),
(sdf2324.234dfs,NaN),
(234,234fsf,234),
(100,100,100),
(100.100,100)

Liés À La Performance:

À l'aide de map sur for-boucles:

Voir: Quel est le moyen le plus efficace de fusion [1,2] et [7,8] en [[1,7], [2,8]]

zip tests

Remarque: les types de base tels que l' false et undefined ne pas posséder une prototypes objet de la hiérarchie et donc de ne pas exposer un toString fonction. Par conséquent ceux-ci sont présentés comme vide dans la sortie.
En tant que parseInts'deuxième argument est la base de/nombre radix, qui pour convertir le nombre d', et depuis map passe l'index en tant que deuxième argument à son argument de la fonction, une fonction wrapper est utilisé.

3voto

Amber Points 159296

Pas intégré à Javascript lui-même. Certains les frameworks Javascript communs (tels que Prototype) fournissent une implémentation, ou vous pouvez écrire votre propre.

0voto

Keith Points 13800

La bibliothèque Mochikit fournit cela et bien d’autres fonctions comme Python. développeur de Mochikit est également un fan de Python, donc il a le style général de Python, et aussi les enveloppes l’async appelle dans un cadre de type tordu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X