两个或多个数组的 Zipping,这就像把不同口袋里的零食倒在一起,拼成一盒豪华版“数组什锦礼包”。想象一下
const arrays = [['a', 'b'], [1, 2], [true, false]];
const zipped = [['a', 1, true], ['b', 2, false]];
瞧,现在是不是觉得Zipping这个概念像是在玩一场数组元素的交换游戏呢?就差开派对庆祝了!
压缩数组
压缩数组需要创建一个数组,长度为参数中最长数组的长度。我们可以使用 Math.max()
和展开运算符 (...)
来获取数组中最长的子数组,然后使用 Array.from()
来创建适当长度的数组。
然后,我们可以使用 Array.prototype.map()
,为新数组的每个元素创建一个数组。每个数组的长度就是传递给函数的参数个数。使用 Array.from()
中的最后一个参数,我们可以映射原始数组的索引,并用该索引处的元素创建一个新数组.
const zip = (...arrays) => {const maxLength = Math.max(...arrays.map(x => x.length));return Array.from({ length: maxLength }).map((_, i) => {return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);});
};zip(['a', 'b'], [1, 2], [true, false]); // [['a', 1, true], ['b', 2, false]]
zip(['a'], [1, 2], [true, false]); // [['a', 1, true], [undefined, 2, false]]
解压数组
压缩
的逆操作是解压
,它将数组的数组重新转换为独立的数组。我们可以使用Math.max()
函数和扩展运算符(...)
来获取数组中最长的子数组,然后利用Array.from()
方法创建一个适当长度的新数组。
接下来,通过使用Array.prototype.reduce()
和Array.prototype.forEach()
方法,我们可以通过将每个值推送到相同索引处的数组中,从而将分组的值映射到各个独立的数组上。
const unzip = arr =>arr.reduce((acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),Array.from({length: Math.max(...arr.map(x => x.length))}).map(x => []));unzip([['a', 1, true], ['b', 2, false]]); // [['a', 'b'], [1, 2], [true, false]]
unzip([['a', 1, true], ['b', 2]]); // [['a', 'b'], [1, 2], [true]]
将数组压缩为对象
若要将数组zip
成一个对象,您可以采用与数组压缩类似的技术。唯一的区别在于您需要使用Array.prototype.reduce()
方法来将键值对分配给对象。
const zipObject = (props, values) =>props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {});zipObject(['a', 'b', 'c'], [1, 2]); // {a: 1, b: 2, c: undefined}
zipObject(['a', 'b'], [1, 2, 3]); // {a: 1, b: 2}
将对象解压缩到数组
将对象解压为一对数组的操作相对简单。您可以利用Object.keys()
和Object.values()
方法分别获取该对象作为数组形式的键和值。
const unzipObject = obj => [Object.keys(obj),Object.values(obj)
];unzipObject({a: 1, b: 2, c: 3}); // [['a', 'b', 'c'], [1, 2, 3]]
unzipObject({a: 1, b: 2}); // [['a', 'b'], [1, 2]]
尾记
该文章参考于
30secondsofcode
的zip-array-into-object