面试中经常会遇到一道扁平化数组的题目:写一个函数,将输入数组 [1, [2, [3, [4]], 5]]
转化为 [1, 2, 3, 4, 5]
的形式。
一开始,我以为是通过此题来考察递归的使用,后来仔细一想,事情远远不止这么简单,本文试着通过几种方式的实现,来理解此题可能要考察的内容。
递归
递归是首选思路,一般人都会想到这个方法,但如果此题只是考察递归的话,是不会这么出题的。
function flatten (arr) {
var result = [];
(function(arr) {
var self = arguments.callee;
arr.forEach(function(item) {
// Array.isArray(item)
if(item instanceof Array) {
self(item);
} else {
result.push(item);
}
});
})(arr);
return result;
}
隐式类型转换
主要考察数组toString()
、valueOf()
方法的使用,这种情况只适合数组元素类型为String和Number,其他情况都会转换为String类型
// 借用数组的toString方法
function flatten (arr) {
var str = arr.toString();
return str.split(',');
}
// 借用数组的valueOf方法
Array.prototype.valueOf = function() {
return this.join(',')
};
function flatten2 (arr) {
var str = arr.valueOf();
return str.split(',');
}
Generator
考察ES6中Generator函数的使用,以及返回值作为一个遍历器对象的使用,以及数组...(扩展运算符)的使用。
function *_flatten (arr) {
for(let i = 0; i < arr.length; i++) {
const item = arr[i];
if(Array.isArray(item)) {
yield *_flatten(item);
} else {
yield item;
}
}
}
const flatten = arr => [..._flatten(arr)];
Symbol.iterator
考察ES6中Symbol.iterator的使用
Array.prototype[Symbol.iterator] = function () {
let arr = [].concat(this);
let first = function (arr) {
return arr.shift();
};
return {
next: function() {
let item = first(arr);
if (item) {
return {
value: item.toString(),
done: false
}
} else {
return {
done: true
}
}
}
};
}
const flatten = arr => {
let res = [];
for(let i of arr) {
res.push(i);
}
return res.join(',').split(',');
};
或者通过generator函数+递归实现
Array.prototype[Symbol.iterator] = function* (array) {
let arr = array || this;
let sel = arguments.callee;
for(let i = 0; i < arr.length; i++) {
const item = arr[i];
if(Array.isArray(item)) {
yield *sel(item);
} else {
yield item;
}
}
}
// test
var arr = [1, [2, [3, [4]], '5']];
console.log([...arr]);
...扩展运算符+Array.prototype.some
function flatten(arr) {
var arr;
while (arr.some(v => Array.isArray(v))) {
arr = [].concat(...arr);
}
return arr;
}
Array.prototype.flat()
flat()
是ES6中新增的数组方法,该方法返回一个新数组,对原数据没有影响。
[1, [2, [3, [4]], 5]].flat(Infinity);
参考:面试题之-扁平化数组
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。