Actualización 2016:
Aquí hay una versión más elegante de Ecmascript 6:
zip= rows=>rows[0].map((_,c)=>rows.map(row=>row[c]))
Ilustración equiv. a Python { zip(*args)
}:
> zip([['row0col0', 'row0col1', 'row0col2'],
['row1col0', 'row1col1', 'row1col2']]);
[["row0col0","row1col0"],
["row0col1","row1col1"],
["row0col2","row1col2"]]
(y FizzyTea señala que ES6 tiene una sintaxis de argumento variable, por lo que la siguiente definición de función actuará como python, pero vea a continuación el descargo de responsabilidad ... esto no será su propio inverso, por zip(zip(x))
lo que no será igual x
; aunque como señala Matt Kramer zip(...zip(...x))==x
(como en pitón normal zip(*zip(*x))==x
))
Definición 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
(Tenga en cuenta que la ...
sintaxis puede tener problemas de rendimiento en este momento, y posiblemente en el futuro, por lo que si usa la segunda respuesta con argumentos variables, es posible que desee probarla).
Aquí hay una línea:
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(...)
Lo anterior supone que las matrices son del mismo tamaño, como deberían ser. También supone que pasa una sola lista de argumentos de listas, a diferencia de la versión de Python donde la lista de argumentos es variada. Si desea todas estas "características", consulte a continuación. Solo toma alrededor de 2 líneas adicionales de código.
Lo siguiente imitará el zip
comportamiento de Python en casos extremos donde las matrices no son del mismo tamaño, simulando en silencio que las partes más largas de las matrices no existen:
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()
// []
Esto imitará el itertools.zip_longest
comportamiento de Python , insertando undefined
donde las matrices no están definidas:
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 utiliza estas dos últimas versiones (también conocidas como versiones variadas de argumentos múltiples), entonces zip ya no es su propio inverso. Para imitar el zip(*[...])
idioma de Python, deberá hacerlo zip.apply(this, [...])
cuando desee invertir la función zip o si desea tener un número variable de listas como entrada.
Anexo :
Para hacer que este maneje sea iterable (por ejemplo, en Python puede usar zip
cadenas, rangos, objetos de mapa, etc.), puede definir lo siguiente:
function iterView(iterable) {
// returns an array equivalent to the iterable
}
Sin embargo, si escribe zip
de la siguiente manera , incluso eso no será necesario:
function zip(arrays) {
return Array.apply(null,Array(arrays[0].length)).map(function(_,i){
return arrays.map(function(array){return array[i]})
});
}
Manifestación:
> JSON.stringify( zip(['abcde',[1,2,3,4,5]]) )
[["a",1],["b",2],["c",3],["d",4],["e",5]]
(O podría usar una range(...)
función de estilo Python si ya ha escrito una. Eventualmente podrá usar comprensiones o generadores de matriz ECMAScript).