YvetteLau / Step-By-Step

不积跬步,无以至千里;
705 stars 66 forks source link

请实现一个 flattenDeep 函数,将嵌套的数组扁平化 #27

Open YvetteLau opened 5 years ago

YvetteLau commented 5 years ago

如:

flattenDeep([1, [2, [3, [4]], 5]])   // [ 1, 2, 3, 4, 5 ]
Sakura-pgh commented 5 years ago
const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));

image

luohong123 commented 5 years ago
function flattenDeep(arr) {
  if(!(arr instanceof Array)) {
    throw 'Please pass in the array.'
  }
  // 使用map 函数判断每一个元素,如果是数组,递归返回一个一维数组,如果不是返回这个元素,最后通过 concat 方法把所有的一维数组合并,返回一维数组
  return [].concat(...arr.map(x => Array.isArray(x) ? flattenDeep(x) :x)) 
}
var arr1 = [1, [2, [3, [4]], 5]];
var oneDim = flattenDeep(arr1)
console.log(oneDim);  // [1,2,3,4,5]
shenanheng commented 5 years ago
const flattenDeep = (arr => {
    let newArray = [];
    return (arr, flag) => {
      arr.forEach(element => {
        if (element instanceof Array) {
          flattenDeep(element, true);
        } else {
          newArray.push(element);
        }
      });
      // 防止重复添加
      let array = JSON.parse(JSON.stringify(newArray));
      if (!flag) {
        newArray = [];
        return array;
      }
    };
  })();
  console.log(flattenDeep([1, [2, [3, [4]], 5]]));
KRISACHAN commented 5 years ago

方法一,栈,先入后出,后入先出

const arr = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12]]]];
const flattenDeep = arr => {
    const resArr = [];
    while (arr.length > 0) {
        const next = arr.pop();
        if (Object.prototype.toString.call(next) === '[array Object]') {
                arr.push(...next);
        } else {
            resArr.push(next);  
        };
    };
    return resArr.reverse();
};

方法二,flat deep max floor

const arr = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12]]]];
const flattenDeep = arr => arr.flat(Math.pow(2, 23) - 1);
clark-maybe commented 5 years ago
function doSomething() {
    let returnArr = [];
    return function loop(arr) {
        for(let t of arr){
            if(!Array.isArray(t)){
                returnArr.push(t);
            }else{
                returnArr.concat(loop(t));
            }
        }
        return returnArr;
    }
}
let loop = doSomething();
console.log(loop([1,[2,[3,[4,[5]]]]]));

还有个toString().split(‘,’)的方法,不过取巧了,会有类型问题.

以上

AILINGANGEL commented 5 years ago
function flattenDeep(arr) {
    return arr.reduce((acc, item) => Array.isArray(item) ? acc.concat(flattenDeep(item)) : acc.concat(item), []);
}
shenshuangdao commented 5 years ago

方法一

方法二 image undefined会有问题

zsf82829060 commented 5 years ago

方法一 const flattenDeep = arr => { return arr.flat(Infinity); };

方法二

const flattenDeep = arr => { return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []); };

mdchun commented 5 years ago

toString

该方法可以用于简单数据处理,

const flattenDeep = (data) => data.toString().split(',').map(Number)

flattenDeep([1, [2, [3, [4]], 5]]) // [ 1, 2, 3, 4, 5 ]

flat 方法

暂未纳入标准,存在兼容问题,谨慎使用

const flattenDeep = (arr) => arr.flat(Infinity) 

flattenDeep([1, [2, [3, [4]], 5]]) // [ 1, 2, 3, 4, 5 ]

递归循环

const flattenDeep = (data) => {
  let ret = []
  data.forEach(item => {
    if(Array.isArray(item)){
      ret = ret.concat(flattenDeep(item))
    } else {
      ret.push(item)
    }
  })
  return ret;
}

flattenDeep([1, [2, [3, [4]], 5]]) // [ 1, 2, 3, 4, 5 ]

reduce

const flattenDeep = (arr) => arr.reduce((cur,pre) => cur.concat(Array.isArray(pre) ? flattenDeep(pre) : pre), [])

flattenDeep([1, [2, [3, [4]], 5]]) // [ 1, 2, 3, 4, 5 ]
riluocanyang commented 5 years ago

数组扁平化方法

方法一:递归

function flattenDeep(arr) {
  let newArr = [];
  let len = arr.length;
  for (let i = 0; i < len; i++) {
    if (Array.isArray(arr[i])) {
      newArr = newArr.concat(flattenDeep(arr[i]));
    } else {
      newArr.push(arr[i]);
    }
  }
  return newArr;
}

方法二:扩展运算符

function flattenDeep(arr) {
  [].concat(...arr.map(item => Array.isArray(item) ? flattenDeep(item) : item))
}

方法三:toString + split

function flattenDeep(arr) {
  arr.toString().split(',').map(item => +item)
}

但是此种方法只能正确转换纯数字数组,不能转换带字符串的数组。比如会将[1,'2','3',4]转换为数组[1,2,3,4]

sinaine commented 5 years ago

1.递归

function flatDeep(arry) {
        let returnArray = [];
        if (arry.length == 0) {
          return [];
        }
        arry.forEach(item => {
          if (Object.prototype.toString.call(item) == "[object Array]") {
            returnArray = returnArray.concat(flatDeep(item));
          } else {
            returnArray.push(item);
          }
        });
        return returnArray;
      }     

2.reduce

 function flattenDeep2(arr) {
        return arr.reduce((item, next) => {
          return item.concat(
            Array.isArray(next) ? flattenDeep2(next) : next
          );
        }, []);
      }

3.toString

function flattenDeep3(arr) {
        return arr.toString().split(",");
      }

缺点: 类型可能会丢失或者改变。

daibin0809 commented 5 years ago
tianyuandsb commented 5 years ago

function flatten(arr) { return arr.reduce((prev, next)=> { return prev.concat(Array.isArray(next) ? flatten(next) : next) }, []) }

yelin1994 commented 5 years ago

数组扁平化

ivan0525 commented 5 years ago
YvetteLau commented 5 years ago

利用 Array.prototype.flat

function flattenDeep(arr, deepLength) {
    return arr.flat(deepLength);
}
console.log(flattenDeep([1, [2, [3, [4]], 5]], 3));

利用 reduce 和 concat

function flattenDeep(arr){
    return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
}
console.log(flattenDeep([1, [2, [3, [4]], 5]]));

使用 stack 无限反嵌套多层嵌套数组

function flatten(input) {
    const stack = [...input];
    const res = [];
    while (stack.length) {
        // 使用 pop 从 stack 中取出并移除值
        const next = stack.pop();
        if (Array.isArray(next)) {
            // 使用 push 送回内层数组中的元素,不会改动原始输入 original input
            stack.push(...next);
        } else {
            res.push(next);
        }
    }
    // 使用 reverse 恢复原数组的顺序
    return res.reverse();
}
console.log(flattenDeep([1, [2, [3, [4]], 5]]));
woyiweita commented 5 years ago

对于以上同学回答的一个总结:

第一种方法更简单方便理解,但涉及到兼容性的问题,最后一种方法在理解上稍微吃力且使用了递归但胜在兼容多版本浏览器。

into-piece commented 5 years ago

Array.prototype.flat

[1, [2, [3, [4]], 5, [6]]].flat(Infinity)

递归

const flattenDeep = (function() {
let newArr = [];
return function loop(array) {
if (!(array instanceof Array)) return array;
let len = array.length;
if (len === 0) return array;
array.forEach((item, index) => {
if (item instanceof Array) {
loop(item);
} else {
newArr.push(item);
}
});
return newArr;
};
})();
let arr = [1, [2, [3, [4]], 5, [6]]];
let newArr = flattenDeep(arr);
console.log(newArr);
Cain-kz commented 5 years ago

//1.使用toString()和split(',')方法 function flattenDeep(item){ if(Array.isArray(item)){ var fn1=item.toString().split(',').map(item=>{ return Number(item) }) console.log("toString()+split()",fn1) } } flattenDeep(a)

//2.回调函数
function flatten(arr){
  var res = [];
  for(var i=0;i<arr.length;i++){
    if(Array.isArray(arr[i])){
      res = res.concat(flatten(arr[i]))
    }else{
      res.push(arr[i])
    }
  }
  return res
}
console.log('回调函数',flatten(a))

//3.reduce()和concat()
function deepFlatten2 (arr){
  return [].concat(...arr.map(x => Array.isArray(x) ? deepFlatten2(x) :x)) 
}
var oneDim = deepFlatten2(a)
console.log("concat()",oneDim);

//4.flat
function flattenDeep3(arr,deepLength){
  return arr.flat(Infinity)
}
console.log('flat',flattenDeep3(a))
cute1baby commented 5 years ago

参照上面【Sakura-pgh】大佬和【Aruthor】闭包的写法,整理一下: 第一种:递归方式

const deepFlatten = arr => Array.from(
    new Set([].concat(
            ...arr.map(
                v => Array.isArray(v) ? deepFlatten(v) : v
            )
        )
    )
);

var arr = [1, 4, 6, [3,6,9,10,1,[3,6,1]]];
console.log(deepFlatten(arr));

第二种:递归方式

const deepArray = (arr) => {
    let list = [];
        arr.forEach((item, index) => {
            if(Array.isArray(item)){
                list = list.concat(deepArray(item));
            }else{
                list.push(item);
            }
        })
        return Array.from(new Set(list));
    }
}
var arr = [1, 4, 6, [3,6,9,10,1,[3,6,1]]];
console.log(deepArray(arr));
xdandsl commented 5 years ago
//1,递归
function flattenDeep(arr){
    let deepArr = []
    arr.forEach(element => {
        if(Array.isArray(element)){
            deepArr = deepArr.concat(flattenDeep(element))
        }else{
            deepArr.push(element)
        }
    });
    return deepArr
}
console.log(flattenDeep([1,[2,3,[4,5]]])) //[ 1, 2, 3, 4, 5 ]

//2,map方法
function flattenDeep2(arr){
    //map方法确保得到的是一维数组。cancat可以合并一维数组
    return [].concat(arr.map(item => Array.isArray(item) ? flattenDeep2(item) : item))
}
console.log(flattenDeep([1,[2,3,[4,5],7],[2,3]]))
0xBrooke commented 5 years ago
var arr = [1, [2, 3], [4, [7, 9]], { name: "kk", age: [23, 32] }];
   // 一 递归方法
        function _flattenDeep(arr) {
            var newArr = [];
            if (Array.isArray(arr)) {
                arr.forEach(item => {
                    Array.isArray(item) ? newArr = newArr.concat(_flattenDeep(item)) : newArr.push(item);
                })
            } else {
                return "false"
            }
            return newArr;
        }
        console.log(_flattenDeep(arr));
 // 利用 Array.prototype.flat函数
 function flattenDeep(arr, deepLength) {
            return arr.flat(deepLength);
        }
        console.log(flattenDeep(arr, 3));

flat 详解:https://blog.csdn.net/qq_29055201/article/details/86530254

chongyangwang commented 5 years ago

递归实现

 var arr = [1,2,3,4,[5,6],7,8]
 funcion  getFlat(list){
   var newArr =[]
   if list===[]   return false
   list.forEach(function(item){
      Array.isArray(item)? newArr = newArr.concat(getFlat(item)): newArr = newArr.push(item)
  })
  return newArr;
}
getFlat(arr)

flat实现

  var arr = [1,2,3,4,5,[1,2,3,[4,5,6]]]
   function flattenDeep(list,length){
     return list.flat(length)
   }
  flattenDeep(arr,3)
jodiezhang commented 5 years ago
var arr1=[1,2,3,[1,2,3,4,[2,3,4]]];

function flattenDeep(arr1) {

  return arr1.reduce((acc,val)=>Array.isArray(val)?acc.concat(flattenDeep(val)):acc.concat(val),[]);

}
console.log(flattenDeep(arr1));
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
function flatten(input) {
  const stack=[...input];
  const res=[];
  while (stack.length) {
     const next=stack.pop();
     if(Array.isArray(next)){
       console.log(...next);
       stack.push(...next);
     }else{
       res.push(next);
     }

  }
  return res.reverse();

}

console.log(flatten(arr1));

转载自MDN: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/flat

Liruimin2 commented 5 years ago

function flatter(arr){ var result =[]; for(var i=0;i<arr.length;i++){ if(arr.isArray(arr[i])){ result = result.concat(flatter(arr[i])) }else{ result.push(arr[i])]} } function flattenDeep(arr){ return arr.reduce(function(pre,cur){ if(arr.isArray(pre){ return cur.concat(flatter(pre))}) }else{ return cur.concat(pre)},[] ) }

ZadaWu commented 5 years ago

实现如下:

function isArray (array) {
    return typeof array === 'object' && array instanceof Array
}
var result = []
function flatternDeep(array) {
    if (!isArray(array)) {
        return array
    }
    // 本质上仍旧是需要递归来解决
     array.forEach(arrayItem => {
        if (isArray(arrayItem)) {
            flatternDeep(arrayItem)
        } else {
            result.push(arrayItem)
        }
    })
}
Diamondjcx commented 5 years ago

综合 各位大佬

  1. 利用 flat Array方法
    function flattenDeep(arr, deepLength) {
    return arr.flat(deepLength);
    }
    console.log(flattenDeep([1, [2, [3, [4]], 5]], 3));
  2. 利用 reduce 和 concat 递归取出并连接
    function flattenDeep(arr){
    return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
    }
    console.log(flattenDeep([1, [2, [3, [4]], 5]]));
  3. stack
    function flatten(input) {
    const stack = [...input];
    const res = [];
    while (stack.length) {
        // 使用 pop 从 stack 中取出并移除值
        const next = stack.pop();
        if (Array.isArray(next)) {
            // 使用 push 送回内层数组中的元素,不会改动原始输入 original input
            stack.push(...next);
        } else {
            res.push(next);
        }
    }
    // 使用 reverse 恢复原数组的顺序
    return res.reverse();
    }
    console.log(flattenDeep([1, [2, [3, [4]], 5]]));
MissNanLan commented 5 years ago

原生js

const flatDeep = arr =>[].concat(...arr.map(v => Array.isArray(v) ? flatDeep(v) : v));
const arr  = [1,2,3,4,5,6,7,[8,9,10,[11,12,13]]];
console.log(flatDeep(arr));

运用flat方法

const arr = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12]]]];
const flattenDeep = arr => arr.flat(4);
console.log(flattenDeep(arr));

reduce方法

const arr = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12,[13]]]]];
const flattenDeep = (arr) => arr.reduce((cur,pre) => cur.concat(Array.isArray(pre) ? flattenDeep(pre) : pre), [])
console.log(flattenDeep(arr));