learn
learn copied to clipboard
JavaScript专题之数组扁平化
数组扁平化
数组的扁平化,就是将一个嵌套多层的数组 array (嵌套可以是任何层数)转换为只有一层的数组。
1.递归循环:
function flatten(arr) {
var result = [];
for (var i = 0, len = arr.length; i < len; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
} else {
result.push(arr[i]);
}
}
return result;
}
2.forEach 遍历数组会自动跳过空元素:
const eachFlat = (arr = [], depth = 1) => {
const result = [];
(function flat(arr, depth) {
arr.forEach(item => {
if (Array.isArray(item) && depth > 0) {
flat(item, depth - 1);
} else {
result.push(item);
}
});
})(arr, depth);
return result;
};
eachFlat([1, 2, [3, [4, [5]]]], Infinity); //[1, 2, 3, 4, 5]
3.for...of:
const forFlat = (arr = [], depth = 1) => {
const result = [];
(function flat(arr, depth) {
for (let item of arr) {
if (Array.isArray(item) && depth > 0) {
flat(item, depth - 1);
} else {
// 去除空元素,添加非undefined元素
item !== void 0 && result.push(item);
}
}
})(arr, depth);
return result;
};
4.如果数组的元素都是数字,那么我们可以考虑使用 toString 方法:
function flatten(arr) {
return arr
.toString()
.split(",")
.map(function(item) {
return +item;
});
}
5.既然是对数组进行处理,最终返回一个值,我们就可以考虑使用 reduce 来简化代码:
function flatDeep(arr, d = 1) {
return d > 0
? arr.reduce(
(acc, val) =>
acc.concat(Array.isArray(val) ? flatDeep(val, d - 1) : val),
[]
)
: arr.slice();
}
6.Array.prototype.flat
方法:
var arr = [1, 2, [3, 4]];
// 展开一层数组
arr.flat();
// 等效于
arr.reduce((acc, val) => acc.concat(val), []);
// [1, 2, 3, 4]
7.使用 ES6 扩展运算符:
const flattened = arr => [].concat(...arr);
function flatten(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
underscore 中的 flatten
// 数组扁平化
/**
* 数组扁平化
* @param {Array} input 要处理的数组
* @param {boolean} shallow 是否只扁平一层
* @param {boolean} strict 是否严格处理元素,下面有解释
* @param {Array} output 这是为了方便递归而传递的参数
* 源码地址:https://github.com/jashkenas/underscore/blob/master/underscore.js#L528
*/
function flatten(input, shallow, strict, output) {
// 递归使用的时候会用到output
output = output || [];
var idx = output.length;
for (var i = 0, len = input.length; i < len; i++) {
var value = input[i];
// 如果是数组,就进行处理
if (Array.isArray(value)) {
// 如果是只扁平一层,遍历该数组,依此填入 output
if (shallow) {
var j = 0,
length = value.length;
while (j < length) output[idx++] = value[j++];
}
// 如果是全部扁平就递归,传入已经处理的 output,递归中接着处理 output
else {
flatten(value, shallow, strict, output);
idx = output.length;
}
}
// 不是数组,根据 strict 的值判断是跳过不处理还是放入 output
else if (!strict) {
output[idx++] = value;
}
}
return output;
}
解释下 strict,在代码里我们可以看出,当遍历数组元素时,如果元素不是数组,就会对 strict 取反的结果进行判断,如果设置 strict 为 true,就会跳过不进行任何处理,这意味着可以过滤非数组的元素,举个例子:
var arr = [1, 2, [3, 4]];
console.log(flatten(arr, true, true)); // [3, 4]
那么设置 strict 到底有什么用呢?不急,我们先看下 shallow 和 strct 各种值对应的结果:
- shallow true + strict false :正常扁平一层
- shallow false + strict false :正常扁平所有层
- shallow true + strict true :去掉非数组元素
- shallow false + strict true : 返回一个[]
原文地址:JavaScript 专题之数组扁平化