Aggiornamento 2016:
Ecco una versione di Snazzier Ecmascript 6:
zip= rows=>rows[0].map((_,c)=>rows.map(row=>row[c]))
Illustrazione equiv. a Python { zip(*args)
}:
> zip([['row0col0', 'row0col1', 'row0col2'],
['row1col0', 'row1col1', 'row1col2']]);
[["row0col0","row1col0"],
["row0col1","row1col1"],
["row0col2","row1col2"]]
(e FizzyTea sottolinea che ES6 ha una sintassi dell'argomento variadico, quindi la seguente definizione di funzione agirà come python, ma vedi sotto per disclaimer ... questo non sarà il suo zip(zip(x))
contrario quindi non sarà uguale x
; sebbene come sottolinea Matt Kramer zip(...zip(...x))==x
(come in pitone normale zip(*zip(*x))==x
))
Definizione alternativa equiv. a Python { zip
}:
> zip = (...rows) => [...rows[0]].map((_,c) => rows.map(row => row[c]))
> zip( ['row0col0', 'row0col1', 'row0col2'] ,
['row1col0', 'row1col1', 'row1col2'] );
// note zip(row0,row1), not zip(matrix)
same answer as above
(Si noti che la ...
sintassi potrebbe avere problemi di prestazioni in questo momento, e forse in futuro, quindi se si utilizza la seconda risposta con argomenti variadici, è possibile che si desideri perfezionarla.)
Ecco 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(...)
Quanto sopra presuppone che le matrici abbiano le stesse dimensioni, come dovrebbero essere. Presuppone anche che passi in un singolo elenco di argomenti list, a differenza della versione di Python in cui l'elenco degli argomenti è variabile. Se vuoi tutte queste "caratteristiche", vedi sotto. Sono necessarie solo circa 2 righe di codice aggiuntive.
Quanto segue imiterà il zip
comportamento di Python in casi limite in cui le matrici non hanno le stesse dimensioni, fingendo silenziosamente che non esistano parti più lunghe delle matrici:
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()
// []
Questo imiterà il itertools.zip_longest
comportamento di Python , inserendo undefined
dove non sono definite le matrici:
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()
// []
Se usi queste ultime due versioni (variadic aka. Versioni con argomenti multipli), zip non è più il suo contrario. Per imitare il zip(*[...])
linguaggio di Python, dovrai farlo zip.apply(this, [...])
quando vuoi invertire la funzione zip o se vuoi avere un numero variabile di liste come input.
addendum :
Per rendere questo handle qualsiasi iterabile (ad esempio in Python è possibile utilizzare zip
stringhe, intervalli, oggetti mappa, ecc.), È possibile definire quanto segue:
function iterView(iterable) {
// returns an array equivalent to the iterable
}
Tuttavia, se scrivi zip
nel modo seguente , anche quello non sarà necessario:
function zip(arrays) {
return Array.apply(null,Array(arrays[0].length)).map(function(_,i){
return arrays.map(function(array){return array[i]})
});
}
demo:
> JSON.stringify( zip(['abcde',[1,2,3,4,5]]) )
[["a",1],["b",2],["c",3],["d",4],["e",5]]
(Oppure potresti usare una range(...)
funzione in stile Python se ne hai già scritta una. Alla fine sarai in grado di usare la comprensione o i generatori di array ECMAScript.)