Aktualizacja 2016:
Oto wersja Ecnacript 6 Snazziera:
zip= rows=>rows[0].map((_,c)=>rows.map(row=>row[c]))
Ilustracja ekwiwal. do Pythona { zip(*args)
}:
> zip([['row0col0', 'row0col1', 'row0col2'],
['row1col0', 'row1col1', 'row1col2']]);
[["row0col0","row1col0"],
["row0col1","row1col1"],
["row0col2","row1col2"]]
(a FizzyTea wskazuje, że ES6 ma składnię argumentów variadic, więc poniższa definicja funkcji będzie działać jak python, ale zobacz poniżej zrzeczenie się odpowiedzialności ... nie będzie to jej własna odwrotność, więc zip(zip(x))
nie będzie równa x
; chociaż, jak zauważa Matt Kramer zip(...zip(...x))==x
(jak w zwykłym pythoniezip(*zip(*x))==x
))
Alternatywna definicja ekwiwal. do Pythona { 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
(Należy pamiętać, że ...
składni mogą występować problemy z wydajnością w tym czasie i być może w przyszłości, więc jeśli użyjesz drugiej odpowiedzi z argumentami variadic, możesz ją dokładnie przetestować).
Oto 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(...)
Powyższe zakłada, że tablice są równej wielkości, tak jak powinny. Zakłada się także, że przekazujesz argument z jednej listy list, w przeciwieństwie do wersji Pythona, w której lista argumentów jest variadic.Jeśli chcesz wszystkie te „funkcje”, patrz poniżej. Zajmuje to około 2 dodatkowe linie kodu.
Poniższe będzie naśladować zip
zachowanie Pythona w przypadkach krawędziowych, w których tablice nie są równej wielkości, w milczeniu udając, że dłuższe części tablic nie istnieją:
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()
// []
To naśladuje itertools.zip_longest
zachowanie Pythona , wstawiając undefined
tam , gdzie tablice nie są zdefiniowane:
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()
// []
Jeśli użyjesz tych dwóch ostatnich wersji (variadic aka. Wersje z wieloma argumentami), zip nie będzie już własną odwrotnością. Aby naśladować zip(*[...])
idiom z Pythona, musisz to zrobić, zip.apply(this, [...])
gdy chcesz odwrócić funkcję zip lub jeśli podobnie chcesz mieć zmienną liczbę list jako dane wejściowe.
uzupełnienie :
Aby uczynić ten uchwyt dowolną iterowalną (np. W Pythonie możesz używać zip
na ciągach, zakresach, obiektach mapy itp.), Możesz zdefiniować:
function iterView(iterable) {
// returns an array equivalent to the iterable
}
Jeśli jednak napiszesz zip
w następujący sposób , nawet to nie będzie konieczne:
function zip(arrays) {
return Array.apply(null,Array(arrays[0].length)).map(function(_,i){
return arrays.map(function(array){return array[i]})
});
}
Próbny:
> JSON.stringify( zip(['abcde',[1,2,3,4,5]]) )
[["a",1],["b",2],["c",3],["d",4],["e",5]]
(Lub możesz użyć range(...)
funkcji w stylu Pythona, jeśli już ją napisałeś. W końcu będziesz mógł używać wyrażeń tablicowych ECMAScript lub generatorów.)