Closed BetaSu closed 2 years ago
直接使用ES6的方法flat
// 方法一
function flat(arr){
const res = []
for(let i=0;i<arr.length;i++){
if(Array.isArray(arr[i])){
for(let j=0;j<arr[i].length;j++){
res.push(arr[i][j])
}
} else {
res.push(arr[i])
}
}
}
// 方法二
function flat(arr){
const res = []
for(x of arr){
res.concat(x)
}
return res
}
// 方法三
arr.reduce((acc,cur) => acc.concat(cur),[])
// 方法四
[].concat(...arr)
// 方法五
[].concat.apply(null,arr)
// 方法一
function flat(arr,res = []){
arr.forEach(item => {
Array.isArray(item) ? flat(item,res): res.push(item)
})
return res
}
// 方法二
function flat(arr){
return arr.reduce((acc,cur) => {
return Array.isArray(cur) ? acc.concat(flat(cur)) : acc.concat(cur)
},[])
}
// 方法三
function flat(arr){
while(arr.some(item => Array.isArray(item))){
arr = [].concat(...arr)
}
return arr
}
// 方法四(要求所有元素数据类型相同,以数字型数组为例)
function flat_numberArray(arr){
return arr.toString().split(',').map(x => Number(x))
}
const arr = [1, [2, 3, [4], 5], 6]
const { isArray } = Array
const flatten = (arr) =>
arr.reduce((acc, cur) => {
return acc.concat(isArray(cur) ? flatten(cur) : cur)
}, [])
const _arr = flatten(arr)
console.log(_arr) // [ 1, 2, 3, 4, 5, 6 ]
const arr = [1, [2, 3, [4], 5], 6]
const len = (arr) => arr.length
const { isArray } = Array
const flatten = (arr) => {
const stack = [...arr]
const res = []
while (len(stack)) {
const f = stack.shift()
if (isArray(f)) {
stack.unshift(...f)
} else {
res.push(f)
}
}
return res
}
const _arr = flatten(arr)
console.log(_arr)
// 实现方式一:reduce
const flatten = arr => arr.reduce((res, cur) => res.concat(Array.isArray(cur) ? flatten(cur) : cur), []);
// 实现方式二:tostring
const flatten2 = arr => arr.toString().split(',').map(item => Number(item));
// 实现方式三:join
const flatten3 = arr => arr.join().split(',').map(item => Number(item));
// 实现方式四:flat(Infinity)
const flatten4 = arr => arr.flat(Infinity);
// 实现方式五:正则
const flatten5 = arr => JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g,'') + ']');
// 实现方式六:扩展运算符
const flatten6 = arr => {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
};
arr.flat(Infinity)
ES6原生支持Array.prototype.flat
// 之前写的,直接拿来用一下
// 判断是否为数组
const isArray = Array.isArray
// 减少一级数组的嵌套深度
const flatten = (array) => flattenDepth(array)
// 深层次扁平化数组
const flattenDeep = (array) => flattenDepth(array, Infinity)
// 根据用户层级扁平化数组,默认一层
const flattenDepth = (array, depth = 1) => {
// 如果不是数组,返回传入的参数
if (!isArray(array)) return array
// 定义当前扁平化层级
let current = 0
const flat = (array, depth, currentDepth) => {
// 声明 result,作为结果返回
let result = []
// 遍历数组
for (const item of array) {
// 如果是数组且遍历深度不大于指定深度, 继续扁平化
if (isArray(item) && currentDepth + 1 <= depth) {
result.push(...flat(item, depth, currentDepth + 1))
} else {
// 否则,插入结果
result.push(item)
}
}
// 返回结果
return result
}
return flat(array, depth, current)
}
// 测试
// 一维
const test1 = () => {
const array = [1, 2, 3]
console.log(`flatten1:`, flatten(array)) // flatten1: (3) [1, 2, 3]
console.log(`flattenDeep1:`, flattenDeep(array)) // flattenDeep1: (3) [1, 2, 3]
}
// 二维
const test2 = () => {
const array = [[1], [2], [3]]
console.log(`flatten2:`, flatten(array)) // flatten2: (3) [1, 2, 3]
console.log(`flattenDeep2:`, flattenDeep(array)) // flattenDeep2: (3) [1, 2, 3]
}
// 三维
const test3 = () => {
const array = [[[1]], [[2]], [[3]]]
console.log(`flatten3:`, flatten(array)) // flatten3: (3) [Array(1), Array(1), Array(1)]
console.log(`flattenDeep3:`, flattenDeep(array)) // flattenDeep3: (3) [1, 2, 3]
}
// 多维
const test4 = () => {
const array = [[[[1]]], [[[2]]], [[[3]]]]
console.log(`flatten:`, flatten(array)) // flatten4: (3) [Array(1), Array(1), Array(1)] 粘的浏览器打印结果,无法展开
console.log(`flattenDeep:`, flattenDeep(array)) // flattenDeep4: (3) [1, 2, 3]
}
const runTest = () => {
test1()
test2()
test3()
test4()
}
runTest()
原生数组方法
function fn1(arr = []) {
return arr.flat(Infinity)
}
递归
function fn2(arr = []) {
return arr.reduce((pre, cur) => {
if (Array.isArray(cur)) {
pre.push(...fn2(cur))
} else {
pre.push(cur);
}
return pre;
}, [])
}
迭代器
function fn3(arr = []) {
function* iteration(arr) {
for (let item of arr) {
if (Array.isArray(item)) {
// 转移迭代器控制权
yield* iteration(item)
} else {
yield item
}
}
}
return [...iteration(arr)];
}
栈存取
function fn4(arr = []) {
// 避免修改原数组
arr = arr.slice()
const res = [];
while (arr.length) {
// 获取头部
const value = arr.shift();
// 是数组的话解构放回头部
if (Array.isArray(value)) {
arr.unshift(...value)
} else {
res.push(value)
}
}
return res;
}
遍历
第四个方法的优化版本,相比方法四,考虑不改变原数组的情况下,也只需要一个额外数组
function fn5(arr = []) {
// 避免修改原数组
const res = arr.slice()
for (let i = 0; i < res.length; i++) {
const value = res[i];
if (Array.isArray(value)) {
// 将数据解构插入原来元素的位置
res.splice(i, 1, ...value);
// 修正指针位置
i--;
}
}
return res;
}
let arr = [1, [2, 3, [4], 5], 6]
console.log(fn1(arr));
console.log(fn2(arr));
console.log(fn3(arr));
console.log(fn4(arr));
console.log(fn5(arr));
输出:
可以分情况进行讨论 arr为我们需要扁平的数组
示例中使用箭头函数,要求node版本至少大于4.0.0,可以使用function方式定义flatten方法 示例中使用的spread运算符,要求node版本至少大于5.0.0,当node版本小于5.0.0时,可以使用其它方法实现
a. 已经知数组维度为n:
arr = arr.flat(n)
b.未知数组维度:
arr = arr.flat(Infinity)
c. n为2
arr.flatMap(el => el)
a. stack
const flatten = (arr) => {
// copy数组
const stackArr = [...arr];
const res = [];
while (stackArr.length) {
const part = stackArr.shift();
if (Array.isArray(part)) {
stackArr.unshift(...part);
} else {
res.push(part);
}
}
return res;
}
b. for循环
const flatten = (arr) => {
var res = [];
for (let i = 0, length = arr.length; i < length; i++) {
if (Array.isArray(arr[i])) {
res.push(...flatten(arr[i]));
} else {
res.push(arr[i]);
}
}
return res;
}
c. reduce
const flatten = (arr) => {
return arr.reduce((prev, next) => {
return prev.concat(Array.isArray(next) ? flatten(next) : next)
}, [])
}
这里的reset运算符的使用可以替换成concat方法
d. while
const flatten = (arr) => {
while (arr.some(el => Array.isArray(el))) {
arr = [].concat(...arr);
}
return arr;
}
同样的,这里的reset运算符也可以使用concat方法
e. 翻版递归
yield需要node版本大于4.0.0
function* flatten(arr) { for (const el of arr) { if(Array.isArray(el)){ yield* flatten(el) } else { yield el } } } const newArr = [...flatten(arr)]
数组为纯数字数组,且n维
const flatten = (arr) => { return arr.toString().split(',').map(el => { return +el }) }
arr.flat(Infinity);
arr.toString().split(',').map(Number)
const myFlat = (arr) => {
const helper = (arr) => {
let res = [];
for (const item of arr) {
if (typeof item === 'object') {
res.push(...item);
} else {
res.push(item);
}
}
return res;
};
while (arr.some(item => typeof item === 'object')) {
arr = helper(arr);
}
return arr;
};
const myFlat1 = (input) => {
const stack = [...input];
const res = [];
while (stack.length) {
const next = stack.pop();
if (Array.isArray(next)) {
stack.push(...next);
} else {
res.push(next);
}
}
return res.reverse();
};
function myFlat3(arr) {
let str = JSON.stringify(arr);
// 过滤所有的中中括号
str = str.replace(/(\[|\])/g, '');
str = '[' + str + ']';
return JSON.parse(str);
}
function* myFlat2(array, depth = 1) {
for (const item of array) {
if (Array.isArray(item) && depth > 0) {
yield* myFlat2(item, depth - 1);
} else {
yield item;
}
}
}
const s = [1, [2, 3, [4], 5], 6] // 函数体 function flatList (list, resList) { resList = resList || [] for (let value of list) { if (Array.isArray(value)) { flatList(value, resList) } else { resList[resList.length] = value } } return resList } // 验证 console.log(flatList(s))
要实现的功能
在 JavaScript 中实现拍平数组,你有几种方法?
代码示例
最佳答案评选标准
最佳答案
childrentime的回答
答题同学须知
答题规范:请在
一次评论
中完成作答,后续修改也请编辑该评论,而不是追加新的评论评选标准:最佳答案由
围观同学
的 👍 和卡颂共同决定评选时间:一般是当日18:00左右评选,如果问题发布当天回答数较少,问题悬赏金额可能增加,同时悬赏时间也会增加
围观同学须知
对于你满意的答案,请不要吝惜你的 👍,这是评选最佳答案的依据
非答题的评论
会被删除,问题相关讨论请在赏金猎人群中进行