Cập nhật năm 2016:
Đây là phiên bản Ecmascript 6 snazzier:
zip= rows=>rows[0].map((_,c)=>rows.map(row=>row[c]))
Minh họa tương đương. tới Python { zip(*args)
}:
> zip([['row0col0', 'row0col1', 'row0col2'],
['row1col0', 'row1col1', 'row1col2']]);
[["row0col0","row1col0"],
["row0col1","row1col1"],
["row0col2","row1col2"]]
(và FizzyTea chỉ ra rằng ES6 có cú pháp luận variadic, vì vậy định nghĩa hàm sau đây sẽ đóng vai trò như trăn, nhưng xem dưới đây để từ chối trách nhiệm ... điều này sẽ không được nghịch đảo của riêng mình nên zip(zip(x))
sẽ không bằng nhau x
, mặc dù như Matt Kramer chỉ ra zip(...zip(...x))==x
(như trong trăn thường xuyên zip(*zip(*x))==x
))
Định nghĩa thay thế tương đương. tới 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
(Xin lưu ý rằng ...
cú pháp có thể có vấn đề về hiệu suất tại thời điểm này và có thể trong tương lai, vì vậy nếu bạn sử dụng câu trả lời thứ hai với các đối số có lỗi, bạn có thể muốn kiểm tra hoàn hảo nó.)
Đây là một 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(...)
Các giả định ở trên cho rằng các mảng có kích thước bằng nhau, như chúng phải vậy. Nó cũng giả sử bạn vượt qua trong một danh sách các đối số danh sách, không giống như phiên bản của Python trong đó danh sách đối số là matrixdic. Nếu bạn muốn tất cả các "tính năng" này, xem bên dưới. Chỉ mất khoảng 2 dòng mã.
Phần sau đây sẽ bắt chước zip
hành vi của Python trong các trường hợp cạnh trong đó các mảng không có kích thước bằng nhau, âm thầm giả vờ các phần dài hơn của mảng không tồn tại:
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()
// []
Điều này sẽ bắt chước itertools.zip_longest
hành vi của Python , chèn vào undefined
nơi các mảng không được xác định:
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()
// []
Nếu bạn sử dụng hai phiên bản cuối cùng này (matrixdic aka. Phiên bản nhiều đối số), thì zip không còn là nghịch đảo của chính nó. Để bắt chước zip(*[...])
thành ngữ từ Python, bạn sẽ cần phải làm zip.apply(this, [...])
khi bạn muốn đảo ngược chức năng zip hoặc nếu bạn muốn có một số lượng danh sách khác nhau làm đầu vào.
phụ lục :
Để làm cho điều này xử lý bất kỳ lần lặp nào (ví dụ: trong Python bạn có thể sử dụng zip
trên chuỗi, phạm vi, đối tượng bản đồ, v.v.), bạn có thể định nghĩa như sau:
function iterView(iterable) {
// returns an array equivalent to the iterable
}
Tuy nhiên, nếu bạn viết zip
theo cách sau , thậm chí điều đó sẽ không cần thiết:
function zip(arrays) {
return Array.apply(null,Array(arrays[0].length)).map(function(_,i){
return arrays.map(function(array){return array[i]})
});
}
Bản giới thiệu:
> JSON.stringify( zip(['abcde',[1,2,3,4,5]]) )
[["a",1],["b",2],["c",3],["d",4],["e",5]]
(Hoặc bạn có thể sử dụng range(...)
hàm kiểu Python nếu bạn đã viết một hàm. Cuối cùng, bạn sẽ có thể sử dụng các trình hiểu hoặc trình tạo mảng ECMAScript.)