javascript中是否有类似于Python的zip函数?也就是说,给定多个相等长度的数组,创建一个由对组成的数组。
例如,如果我有三个这样的数组:
var array1 = [1, 2, 3];
var array2 = ['a','b','c'];
var array3 = [4, 5, 6];
输出数组应该是:
var outputArray = [[1,'a',4], [2,'b',5], [3,'c',6]]
javascript中是否有类似于Python的zip函数?也就是说,给定多个相等长度的数组,创建一个由对组成的数组。
例如,如果我有三个这样的数组:
var array1 = [1, 2, 3];
var array2 = ['a','b','c'];
var array3 = [4, 5, 6];
输出数组应该是:
var outputArray = [[1,'a',4], [2,'b',5], [3,'c',6]]
当前回答
惰性生成器解决方案的一个变体:
function* iter(it) { yield* it; } function* zip(...its) { its = its.map(iter); while (true) { let rs = its.map(it => it.next()); if (rs.some(r => r.done)) return; yield rs.map(r => r.value); } } for (let r of zip([1,2,3], [4,5,6,7], [8,9,0,11,22])) console.log(r.join()) // the only change for "longest" is some -> every function* zipLongest(...its) { its = its.map(iter); while (true) { let rs = its.map(it => it.next()); if (rs.every(r => r.done)) return; yield rs.map(r => r.value); } } for (let r of zipLongest([1,2,3], [4,5,6,7], [8,9,0,11,22])) console.log(r.join())
这是python经典的“n-group”习语zip(*[iter(a)]*n):
triples = [...zip(...Array(3).fill(iter(a)))]
其他回答
惰性生成器解决方案的一个变体:
function* iter(it) { yield* it; } function* zip(...its) { its = its.map(iter); while (true) { let rs = its.map(it => it.next()); if (rs.some(r => r.done)) return; yield rs.map(r => r.value); } } for (let r of zip([1,2,3], [4,5,6,7], [8,9,0,11,22])) console.log(r.join()) // the only change for "longest" is some -> every function* zipLongest(...its) { its = its.map(iter); while (true) { let rs = its.map(it => it.next()); if (rs.every(r => r.done)) return; yield rs.map(r => r.value); } } for (let r of zipLongest([1,2,3], [4,5,6,7], [8,9,0,11,22])) console.log(r.join())
这是python经典的“n-group”习语zip(*[iter(a)]*n):
triples = [...zip(...Array(3).fill(iter(a)))]
除了ninjagecko出色而全面的回答外,将两个js数组压缩成“元组模拟”所需要的是:
//Arrays: aIn, aOut
Array.prototype.map.call( aIn, function(e,i){return [e, aOut[i]];})
Explanation: Since Javascript doesn't have a tuples type, functions for tuples, lists and sets wasn't a high priority in the language specification. Otherwise, similar behavior is accessible in a straightforward manner via Array map in JS >1.6. (map is actually often implemented by JS engine makers in many >JS 1.4 engines, despite not specified). The major difference to Python's zip, izip,... results from map's functional style, since map requires a function-argument. Additionally it is a function of the Array-instance. One may use Array.prototype.map instead, if an extra declaration for the input is an issue.
例子:
_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]]})
结果:
//'('+_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)
相关的性能:
使用map over for loops:
请参阅:将[1,2]和[7,8]合并为[[1,7],[2,8]的最有效方法是什么
注意:基本类型如false和undefined不具有原型对象层次结构,因此不公开toString函数。因此,这些在输出中显示为空。 由于parseInt的第二个参数是基数/数字基数,要将数字转换为基数/数字基数,并且由于map将索引作为第二个参数传递给它的参数函数,因此使用包装器函数。
带有生成器的现代ES6示例:
function *zip (...iterables){
let iterators = iterables.map(i => i[Symbol.iterator]() )
while (true) {
let results = iterators.map(iter => iter.next() )
if (results.some(res => res.done) ) return
else yield results.map(res => res.value )
}
}
首先,我们得到一个iterables列表作为迭代器。这通常是透明地发生的,但在这里我们明确地进行,因为我们逐步让步,直到其中一个耗尽。我们检查给定数组中的任何结果(使用.some()方法)是否已耗尽,如果是,则中断while循环。
您可以减少数组的数组,并通过获取内部数组的索引的结果来映射新数组。
Var array1 = [1,2,3], Array2 = ['a','b','c'], Array3 = [4,5,6], 数组= [array1, array2, array3], 转置=数组。减少((r) = > a.map ((v, i) = > (r(我)| | []).concat (v)), []); console.log(转置);
有趣的传播。
常量 转置= (r, a) => a.map((v, i) =>[…](r[i] || []), v]), Array1 = [1,2,3], Array2 = ['a','b','c'], Array3 = [4,5,6], 转置= [array1, array2, array3]。减少(转置,[]); console.log(转置);
Python有两个压缩序列的函数:zip和itertools.zip_longest。Javascript中相同功能的实现如下所示:
Python的zip在JS/ES6上的实现
const zip = (...arrays) => {
const length = Math.min(...arrays.map(arr => arr.length));
return Array.from({ length }, (value, index) => arrays.map((array => array[index])));
};
结果:
console.log(zip(
[1, 2, 3, 'a'],
[667, false, -378, '337'],
[111],
[11, 221]
));
[[1, 667, 111, 11]
console.log(zip(
[1, 2, 3, 'a'],
[667, false, -378, '337'],
[111, 212, 323, 433, '1111']
));
[[1、667、111],[2,假的,212年],[3、-378、323],[' a ', “337”,433]]
console.log(zip(
[1, 2, 3, 'a'],
[667, false, -378, '337'],
[111],
[]
));
[]
Python的zip_longest在JS/ES6上的实现
(https://docs.python.org/3.5/library/itertools.html?highlight=zip_longest # itertools.zip_longest)
const zipLongest = (placeholder = undefined, ...arrays) => {
const length = Math.max(...arrays.map(arr => arr.length));
return Array.from(
{ length }, (value, index) => arrays.map(
array => array.length - 1 >= index ? array[index] : placeholder
)
);
};
结果:
console.log(zipLongest(
undefined,
[1, 2, 3, 'a'],
[667, false, -378, '337'],
[111],
[]
));
[[1,667, 111, undefined], [2, false, undefined, undefined], [3, -378, undefined, undefined], ['a', '337', undefined, 未定义
console.log(zipLongest(
null,
[1, 2, 3, 'a'],
[667, false, -378, '337'],
[111],
[]
));
[[1, 667, 111, null], [2, false, null, null], [3, -378, Null, Null], ['a', '337', Null, Null]]
console.log(zipLongest(
'Is None',
[1, 2, 3, 'a'],
[667, false, -378, '337'],
[111],
[]
));
[[1,667, 111, 'Is None'], [2, false, 'Is None', 'Is None'], [3, -378,“没有”,“没有 ' ], [ ' ”、“337”、“没有”、“ 没有']]