Daily-Interview-Question icon indicating copy to clipboard operation
Daily-Interview-Question copied to clipboard

第 36 题:使用迭代的方式实现 flatten 函数

Open Moriarty02 opened this issue 5 years ago • 83 comments

var arr=[1,2,3,[4,5],[6,[7,[8]]]]
/**
 * 使用递归的方式处理
 * wrap内保存结果ret 
 * 返回一个递归函数
 *
 * @returns
 */
function wrap(){
    var ret=[];
    return function flat(a){
        for(var item of a){
            if(item.constructor===Array){
                ret.concat(flat(item))
            }else{
                ret.push(item)
            }
        }
        return ret
    }
}
console.log(wrap()(arr));

将一个多维数组拍平为一个一维数组

Moriarty02 avatar Mar 19 '19 01:03 Moriarty02

const spreadableSymbol = Symbol.isConcatSpreadable
const isFlattenable = (value) => {
  return Array.isArray(value) || (typeof value == 'object' && value !== null
    && Object.prototype.toString.call(value) === '[object Arguments]') ||
    !!(spreadableSymbol && value && value[spreadableSymbol])
}

/**
 * flatten的基本实现,具体可以参考lodash库的flatten源码
 * @param array 需要展开的数组
 * @param depth 展开深度
 * @param predicate 迭代时需要调用的函数
 * @param isStrict 限制通过`predicate`函数检查的值
 * @param result 初始结果值
 * @returns {Array} 返回展开后的数组
 */
function flatten(array, depth, predicate, isStrict, result) {
  predicate || (predicate = isFlattenable)
  result || (result = [])

  if (array == null) {
    return result
  }

  for (const value of array) {
    if (depth > 0 && predicate(value)) {
      if (depth > 1) {
        flatten(value, depth - 1, predicate, isStrict, result)
      } else {
        result.push(...value)
      }
    } else if (!isStrict) {
      result[result.length] = value
    }
  }
  return result
}

flatten([1, 2, 3, [4, 5, [6]]], 2)
// [1, 2, 3, 4, 5, 6]

suguoyao avatar Mar 19 '19 01:03 suguoyao

迭代的实现:

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

const flatten = function (arr) {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr)
    }
    return arr
}

console.log(flatten(arr))

递归的实现(ES6简写):

const flatten = array => array.reduce((acc, cur) => (Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur]), [])

yeyan1996 avatar Mar 19 '19 01:03 yeyan1996

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

迭代实现

    function flatten(arr) {
      let arrs =[...arr]
      let newArr = [];
      while (arrs.length){
        let item = arrs.shift()
        if(Array.isArray(item)){
          arrs.unshift(...item)
        }else {
          newArr.push(item)
        }
      }
      return newArr
    }

递归实现

    function flatten(arr) {
    let arrs = [];
      arr.map(item => {
        if(Array.isArray(item)){
          arrs.push(... flatten(item))
        } else {
          arrs.push(item)
        }
      })
      return arrs
    }

字符串转换

arr.join(',').split(',').map(item => Number(item)))

Rashomon511 avatar Mar 19 '19 02:03 Rashomon511

使用Generator实现数组flatten:

function* flat(arr){
	for(let item of arr){
		if(Array.isArray(item)){
			yield* flat(item);//Generator委托
		}else {
			yield item
		}
	}
}
function flatten(arr) {
	let result = [];
	for(let val of(flat(arr))){
		result.push(val);
	}
	return result;
}
let arr1 = [1,[2,3,[4,5],6],[7]];
console.log(flatten(arr1));//[1, 2, 3, 4, 5, 6, 7]

underlineMY avatar Mar 19 '19 02:03 underlineMY

const arr = [1,2,3,[4,5],6,[7,[8, 9, 10]]]

// 递归
function flatten(arr, res = []) {
    for (let i = 0; i < arr.length; i++) {
        if (typeof arr[i] === 'object') {
            flatten(arr[i], res);
        } else {
            res.push(arr[i]);
        }
    }
    return res;
}

// 队列
function flatten1(arr) {
    const newArr = [...arr];
    const res = [];
    while (newArr.length) {
        const item = newArr.shift(); // 出队
        if (Array.isArray(item)) {
            newArr.unshift(...item); // 入队
        } else {
            res.push(item);
        }
    }
    return res;
}

Ray-56 avatar Mar 19 '19 02:03 Ray-56

/** *

  • @param {Array} arr 需要扁平化的数组
  • @param {Number} [depth=1] 扁平化深度
  • @return {Array} 扁平化后的新数组 */ function flatten(arr, depth = 1) { return arr.reduce((newArr, nextArr) => newArr.concat(depth > 1 && Array.isArray(nextArr) ? flatten(nextArr, depth - 1) : nextArr), []) }

fingerpan avatar Mar 19 '19 05:03 fingerpan

ES10

arr.flat(Infinity);

ringcrl avatar Mar 19 '19 08:03 ringcrl

function flatten(arr) {
  const result = [...arr];
  for (let i = 0; i < result.length; i++) {
    const item = result[i]
    if (Array.isArray(item)) {
      Array.prototype.splice.apply(result, [i, 1, ...item])
      i--
    }
  }
  return result
}

wind-stone avatar Mar 19 '19 10:03 wind-stone

var arr=[1,2,3,[4,5],[6,[7,[8]]]]
function flatten(arr, result){
    if(!result){
        var result = [];
    }
    
    if(Object.prototype.toString.call(arr) == "[object Array]"){
        for (let i=0; i<arr.length; i++){
            if(Object.prototype.toString.call(arr[i]) == "[object Array]"){
                flatten(arr[i], result);
            }else{
                result.push(arr[i]);
            }
        } 
    }
    return result;
}

flatten(arr);

gaomin avatar Mar 20 '19 02:03 gaomin

const flatten = (arr, deep) => {

    deep = deep ? deep : Infinity;
    while(deep && arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr);
        deep --;
    }
    return arr;
}
Array.prototype.flatten = function (deep) {
    
    return flatten(this, deep);
}
[1,[123,["213",["dorsey","123"]]]].flatten();

dorseysen avatar Mar 20 '19 13:03 dorseysen

const flatten = x => x.reduce((pre, cur) => Array.isArray(cur) ? pre.concat(flatten(cur)) : pre.concat(cur), []);

wind1996 avatar Mar 20 '19 16:03 wind1996

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]
arr.toString().split(',')
or
arr.join(',').split(',')

xiaobaichiliangpi avatar Mar 26 '19 02:03 xiaobaichiliangpi

function flatten(a) { return Array.isArray(a) ? [].concat(...a.map(flatten)) : a; }

scq000 avatar Mar 27 '19 10:03 scq000

image

z253573760 avatar Mar 29 '19 07:03 z253573760

为什么我老是喜欢投机取巧,哈哈

var arr = [1,[2,3,[4,5]],8]
function flat (arr) {
  return JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g, '') + ']')
}
flat(arr)

formattedzzz avatar Mar 31 '19 02:03 formattedzzz

const flatten = (arr) => {     
  if(Array.isArray(arr)) {
    return arr.reduce(((res, cur) => res.concat(flatten(cur))), [])
  }else {
    return [arr]
  }
}

cheqianxiao avatar Apr 01 '19 02:04 cheqianxiao

为什么我老是喜欢投机取巧,哈哈

var arr = [1,[2,3,[4,5]],8]
function flat (arr) {
  return JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g, '') + ']')
}
flat(arr)

虽然不是考点,但也没啥不好的。😂

yu910709 avatar Apr 03 '19 08:04 yu910709

为什么我老是喜欢投机取巧,哈哈

var arr = [1,[2,3,[4,5]],8]
function flat (arr) {
  return JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g, '') + ']')
}
flat(arr)

虽然不是考点,但也没啥不好的。😂

这个怎么样😂

[1,[2,3,[4,5]],8].join(',').split(',').map(item => Number(item));

dorseysen avatar Apr 03 '19 09:04 dorseysen

var arr = [1,[2,3,[4,5]],8]
function flatten(arr) {
   return arr.toString().split(",")
}
flatten(arr)
 ["1", "2", "3", "4", "5", "8"]

这样呢?

qinnnn avatar Apr 09 '19 06:04 qinnnn

题目要求的是迭代的方式,各位取巧的同学。。。

function flatten(arr){
	let des = [];
	for(let i in arr){
		const v = arr[i];
		if(Array.isArray(v)){
			des = [...des,...flatten(v)]
			
		} else {
			des.push(v);
			
		}


	}
	return des;
	
}
function flatten(arr){
	let des = [...arr], i = 0;
	while(i <= des.length - 1) {
		if(Array.isArray(des[i])){
			des = [...des.slice(0, i), ...des[i], ...des.slice(i + 1, des.length)]
		} else {
			i++;
		}	
	}
	return des;
}

goodwinfame avatar Apr 09 '19 08:04 goodwinfame

为什么我老是喜欢投机取巧,哈哈

var arr = [1,[2,3,[4,5]],8]
function flat (arr) {
  return JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g, '') + ']')
}
flat(arr)

虽然不是考点,但也没啥不好的。😂

这个怎么样😂

[1,[2,3,[4,5]],8].join(',').split(',').map(item => Number(item));

[1,[2,3,[4,5]],8].toString().split(",").map(Number)

cliYao avatar Apr 17 '19 14:04 cliYao

// reduce
function flatten(arr) {
    return arr.reduce((total, item) => total.concat(Array.isArray(item) ? flatten(item) : [item]), [])
}
// map
function flatten(arr) {
    return [].concat(...arr.map(item => Array.isArray(item) ? flatten(item) : item))
}
// for
function flatten(arr, result = []) {
    for (let item of arr) {
        if (Array.isArray(item)) {
            flatten(item, result)
        } else {
            result.push(item)
        }
    }
    return result
}

LoneYin avatar Apr 24 '19 06:04 LoneYin

function flattern(list) {
  const stack = [...list]
  const des = []
  while (stack.length) {
    const next = stack.pop()
    if (Array.isArray(next)) {
      stack.push(...next)
    } else {
      des.push(next)
    }
  }
  return des.reverse()
}

waningflow avatar May 28 '19 15:05 waningflow

var arr=[1,2,3,[4,5],[6,[7,[8]]]]
/**
 * 使用递归的方式处理
 * wrap内保存结果ret 
 * 返回一个递归函数
 *
 * @returns
 */
function wrap(){
    var ret=[];
    return function flat(a){
        for(var item of a){
            if(item.constructor===Array){
                ret.concat(flat(item))
            }else{
                ret.push(item)
            }
        }
        return ret
    }
}
console.log(wrap()(arr));

将一个多维数组拍平为一个一维数组

ret = ret.concat(flat(item))

liuyanxing avatar Jun 01 '19 15:06 liuyanxing

function flatten(arr, temp = []){
  arr.forEach((item) => {
   if(Array.isArray(item)) {
    flatten(item, temp)
   } else {
    temp.push(item)
   }
  })
  return temp
}

Arrogant128 avatar Jul 16 '19 07:07 Arrogant128

function flatten(arr) {
  if (!Array.isArray(arr) || !arr.length) return [];
  
  const tempArr = []; // 辅助数组
  const result = []; // 用来保存结果

  tempArr.push([arr, 0]);

  while (tempArr.length) {
    const currentArr = tempArr[tempArr.length - 1];
    const [current, index] = currentArr;

    if (index >= current.length) {
      tempArr.pop();
      continue;
    }

    currentArr[1]++; // 下标 + 1

    const currentItem = current[index];
    if (Array.isArray(currentItem)) {
      tempArr.push([currentItem, 0]);
      continue;
    }

    result.push(currentItem);
  }

  return result;
}

AsakuraC avatar Jul 16 '19 09:07 AsakuraC

function flatten(arr,result){ for(let item of arr){ if(Array.isArray(item)){ ...flatten(item,result) }else{ result.push(item) } } }

snowzijun avatar Jul 16 '19 10:07 snowzijun

let attr=[1,2,3,[4,5],[6,[7,[8]]]];
   function flatten(attr){
     if(Array.isArray(attr)){
       let att=[]
        for (let item of attr){
          att=  att.concat(flatten(item))
        }
        return att
     }
     else {
       return attr
     }
   }
flatten (attr)

NANAYWY avatar Jul 19 '19 05:07 NANAYWY

// O(n)
const flat = function(array) {
  let tail = []
  let index = 0
  while (0 < array.length) {
    let elem = array.pop()
    if (Array.isArray(elem)) {
      array.push(...elem)
    } else {
      tail.push(elem)
    }
  }
  return tail.reverse()
}

const nestedArray = [[[1,2],3,[4,[5,6]],7,8],9]
console.log(nestedArray)
console.log(flat(nestedArray))

soc221b avatar Jul 22 '19 07:07 soc221b


function flatten (arr) {
    if (arr.length <=1) return arr;
    const flatArr = [];
    for (let i = 0; i<arr.length; i++) {
        if(Object.prototype.toString.call(arr[i]) == '[object Array]') {
              flatArr = flatArr.concat(flatten(arr[i]))
        } else {
              flatArr.push(arr[i])
        }
    }
    return flatArr
}

let test = [[[1,2,3], 4], 5]
console.log(flatten(test))

mongonice avatar Jul 23 '19 09:07 mongonice

迭代

const flatten = (arr, list = []) => {
  for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      arr = arr.slice(0, i).concat(arr[i]).concat(arr.slice(i + 1))
      i--
    } else {
      list.push(arr[i])
    }
  }
  return list
}

递归

const flat = (arr, list = []) => {
  if (!Array.isArray(arr)) return list.push(arr)
  arr.forEach(item => flat(item, list))
  return list
}

yesixuan avatar Jul 29 '19 03:07 yesixuan

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), []);
}
flattenDeep(arr1);

nordon-wang avatar Aug 19 '19 02:08 nordon-wang

//我的最"笨"的迭代方法
function flat_arr(arr,new_arr){
	for(let i=0;i<arr.length;i++){
		let item=arr[i];
		if(Array.isArray(item)){
			 flat_arr(item,new_arr);
		}else{
			new_arr.push(item)
		}
		
  }
}

var arr=[1,2,3,[4,5],[6,[7,[8]]]]

var new_arr=[];

flat_arr(arr,new_arr)
console.log(new_arr)

ES6的flat函数

var arr=[1,2,3,[4,5],[6,[7,[8]]]]
arr.flat(Infinity);

daiyunchao avatar Aug 20 '19 10:08 daiyunchao

迭代的实现:

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

const flatten = function (arr) {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr)
    }
    return arr
}

console.log(flatten(arr))

递归的实现(ES6简写):

const flatten = array => array.reduce((acc, cur) => (Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur]), [])

很棒的思路,Array.some那句有点冗余,可以这样写 const flatten = function (arr) { while (arr.some(Array.isArray)) { arr = [].concat(...arr) } return arr }

YoungNK avatar Aug 27 '19 02:08 YoungNK

迭代的实现:

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

const flatten = function (arr) {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr)
    }
    return arr
}

console.log(flatten(arr))

递归的实现(ES6简写):

const flatten = array => array.reduce((acc, cur) => (Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur]), [])

使用 some 判断 怎么会一遍一遍把 arr 扩展吗?有谁可以解释下吗?

huangd-d avatar Sep 23 '19 06:09 huangd-d

  function flattern(arr) {
      var result = []
      arr.forEach(item => {
        result = Array.isArray(item) ? result.concat(flattern(item))  :result.concat(item)
      })
      return result
    }

aeolusheath avatar Oct 10 '19 10:10 aeolusheath

function flatten(arr){
  return arr.reduce(function(pre, cur){
    if(Array.isArray(cur)){
      return pre.concat(flatten(cur))
    } else {
      return pre.concat(cur)
    }
  }, [])
}

YuArtian avatar Oct 10 '19 14:10 YuArtian

var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
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();
}
flatten(arr1);// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]

irina9215 avatar Oct 23 '19 07:10 irina9215

一行代码:

const flatten = arr => arr.some(item => Array.isArray(item)) ? flatten([].concat(...arr)) : arr;

const flatten = arr => arr.reduce((acc, cur) => (Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur]), []);

tywei90 avatar Nov 04 '19 14:11 tywei90

function flatten(arr) {
  var res = arr;
  var i = 0;
  while (i < res.length) {
    if (Array.isArray(res[i])) {
      res.splice(i, 1, ...res[i]);
    }
    i++;
  }
  console.log(res);
  return res;
} 

flatten([1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, [13, 14, [15, 16]]]]]);

不断迭代,遇到数组的元素,用该数组的解构替换该元素,这样就改变了原数组的长度,继续迭代,进行这种判断和处理。

vinsiny avatar Nov 06 '19 02:11 vinsiny

const flatten = Function.apply.bind([].concat,[])

Gstring-w avatar Nov 07 '19 06:11 Gstring-w

迭代的实现:

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

const flatten = function (arr) {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr)
    }
    return arr
}

console.log(flatten(arr))

递归的实现(ES6简写):

const flatten = array => array.reduce((acc, cur) => (Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur]), [])

牛逼啊,老哥

fireairforce avatar Nov 12 '19 14:11 fireairforce

递归写法

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

toString 「存在限制,对于存在多种类型的数组无法使用」

因为元素的数组都是数字 多层数组直接调用 toString会返回一个扁平的逗号分隔的字符串

[1,[2,[3,4]]].toString() // "1,2,3,4"

所以我们通过先转化成扁平字符串在转化为数字数组实现扁平化

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

reduce

使用数组的reduce累加方法

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

ES6扩展运算符

扩展运算符可以取出参数对象的可遍历属性,拷贝到当前对象之中

var arr = [1, [2, [3, 4]]];
console.log([].concat(...arr)); // [1, 2, [3, 4]]

但一次扩展运算符只能展开一层 我们可以添加循环条件

function flatten(arr) {
  while(arr.some(item => Array.isArray(item))) {
    arr = [].concat(...arr)
  }
  return arr
}

同时我们可以设置出展开特定层数的方法

function flatten(arr, count) {
  while (arr.some(item => Array.isArray(item) && count-- > 0)) {
    arr = [].concat(...arr)
  }
  return arr
}

Generator函数

我们可以使用Generator函数来展开多重数组

function *flatten(arr) {
  for(const item of arr) {
    if (Array.isArray(item)) {
      yield *flatten(item)
    } else {
      yield item
    }
  }
}

const flattened = [...flatten([1,2,[3,4,[5,6]]])];  // [1,2,3,4,5,6]

Reaper622 avatar Dec 09 '19 08:12 Reaper622

1. array.reduce
function flattenDeep(ary) {
   return Array.isArray(ary) ? ary.reduce((a,b) => [...a,...flattenDeep(b)],[]) : [ary];
}

2. generator
function* demo(ary) {
        for (let i = 0; i < ary.length; i++) {
            if (Array.isArray(ary[i])) {
                yield* demo(ary[i]);
            } else {
                yield ary[i];
            }
        }
    }
    for (let f of demo(ary)) {
        console.log(f);
    }

SnailOwO avatar Dec 30 '19 09:12 SnailOwO

1.使用栈的思想实现 flat 函数 const flat = (arr) => { const stack = [...arr]; const res = []; while( stack.length ){ const next = stack.pop(); if(Array.isArray(next)){ stack.push(...next); } else { res.push(next) } } return res.reverse(); };

2.reduce + 递归

const flat = (arr) => { return arr.reduce((prv,cur) => { return Array.isArray(cur) ? prv.concat(flat(cur)) : prv.concat(cur) },[]) }

wxmac avatar Dec 31 '19 06:12 wxmac

function flatten(arr) {
  for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      arr = arr.concat(arr[i])
      arr.splice(i, 1)
    }
  }
  return arr;
}

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

console.log(flatten(arr))

a1029563229 avatar Dec 31 '19 10:12 a1029563229

let test = [1, 2, [3, 4, 5,[6,7]]]; Array.prototype.myFlat = function () { const result = []; this.forEach(item => { if ((typeof item) !== 'object') { result.push(item); } else { result.push(...Array.prototype.myFlat.apply(item)); } }); return result; }; console.log(test.myFlat());

jinfang12345 avatar Jan 13 '20 11:01 jinfang12345

Array.reduce()

// 数组调用recduce方法时,可以传递两个参数,第一个参数为回调函数,第二个参数为一个初始值。
// 回调函数中需要传递两个参数,第一个参数为每次执行函数的返回值,第二个参数为当前索引对应数组的值。
// reduce的第二个参数是可以省略的,省略的话,回调函数第一次调用的参数为数组的第一项和第二项的值,
// 如果没有省略,回调函数的第一个参数就是这个初始值。
function flatten (arr) {
    return arr.reduce((prev, curr) => {
        return Array.isArray(curr) ? [...prev, ...flatten(curr)] : [...prev, curr]
    }, [])
}

wangyang310 avatar Mar 13 '20 06:03 wangyang310

    栈的写法
let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]
function flat(arr) {
	let stack = []
	let newArr = []
	stack.push(arr)
	while (stack.length) {
		let item = stack.pop()
		if (item.length) {
			for (let i = item.length-1; i >-1; i--) {
				stack.push(item[i])
			}
		} else {
			newArr.push(item)
		}

	}
	return newArr
}
console.log(flat(arr));

13866368297 avatar Mar 19 '20 13:03 13866368297

var arr = [1,[2,3,[4,5]],8]
function flatten(arr) {
   return arr.toString().split(",")
}
flatten(arr)
 ["1", "2", "3", "4", "5", "8"]

这样呢?

应该让元素保持number类型, flatten(arr).map(Number)

alan1111 avatar Jun 24 '20 08:06 alan1111

Iterator 版:

const getIterator = (iteratorable) => iteratorable[Symbol.iterator]()

const getDataType = (data) => Object.prototype.toString.call(data).slice(8,-1)

const isArray = (data) => getDataType(data) === 'Array'

const flatten = (arr,deep=1) => {

  const flatArr = []

  const iteratorFn = (array,dep) => {
    const iterator = getIterator(array)

    while(true){
      const obj = iterator.next()
      if(obj.done){
        break;
      }
      if(isArray(obj.value)&&dep>0){
        dep--
        iteratorFn(obj.value, dep)
      }else{
        flatArr.push(obj.value)
      }
    }
  }
  iteratorFn(arr,deep)
  return flatArr
}
const arr = [1 ,[ 2,3,[4,5,6,[7,8,9,10]]]]

test:

const arr = [1 ,[ 2,3,[4,5,6,[7,8,9,10]]]]
flatten(arr)
// [1, 2, 3, Array(4)]
flatten(arr,2)
// [1, 2, 3, 4, 5, 6, Array(4)]
flatten(arr,3)
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

daolou avatar Jun 24 '20 09:06 daolou

迭代的实现:

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

const flatten = function (arr) {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr)
    }
    return arr
}

console.log(flatten(arr))

递归的实现(ES6简写):

const flatten = array => array.reduce((acc, cur) => (Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur]), [])

使用 reduce 也属于迭代吧?

cutie6 avatar Jun 27 '20 01:06 cutie6

递归 var flatten = (arr) => arr.every(ele => ele?.constructor !== Array) ? arr : flatten([].concat(...arr))

chenyanfei-m avatar Jul 24 '20 13:07 chenyanfei-m

function flat(arr) {
	let ret = [];
	arr.forEach(item => {
		if (+item === item) {
			ret.push(item);
		} else {
			ret = ret.concat(flat(item));
		}
	})
	return ret;
}

tjwyz avatar Jul 27 '20 08:07 tjwyz

队列方式:

function flatten(arr) {
  const ret = [];
  const queue = [];
  let index = 0;

  while (index < arr.length || queue.length) {
    // 取出 queue中的元素然后处理
    const queueLen = queue.length;
    for (let i = 0; i < queueLen; i++) {
      const item = queue.shift();
      if (Array.isArray(item)) {
        for (let j = 0; j < item.length; j++) {
          queue.push(item[j]);
        }
      } else {
        ret.push(item);
      }
    }
    // 取出原数组放入queue
    if (index < arr.length) queue.push(arr[index++]);
  }
  return ret;
}

gitwillsky avatar Aug 20 '20 07:08 gitwillsky

var arr=[1,2,3,[4,5],[6,[7,[8]]]]

function getArr(arr) {

let result=[]

for (let i = 0; i < arr.length; i++) {
    const element = arr[i];
    if(element instanceof Array) {
       result = [...result,...getArr(element)]
    }
    else {
        result.push(element)
    }
}
return result;

}

console.log(getArr(arr))

cc8476 avatar Aug 23 '20 09:08 cc8476

function flatten(arr) {
  if (!arr.length) {
    return []
  }
  let stack = [...arr]
  let res = []
  while (stack.length) {
    let item = stack.pop()
    if (Array.isArray(item)) {
      for (let cld of item) {
        stack.push(cld)
      }
    } else {
      res.unshift(item)
    }
  }
  return res
}

wabRul avatar Sep 04 '20 06:09 wabRul

var arr=[1,2,3,[4,5],[6,[7,[8]]]];
function flatten(arr = []){
    const newArr = [];
    while(arr.length > 0){
        const first = arr.shift();
        if(Array.isArray(first)){
            arr = [...first, ...arr];
        }else {
            newArr.push(first);
        }
    }
    return newArr;
}
console.log(flatten(arr));//  [1, 2, 3, 4, 5, 6, 7, 8]

79percent avatar Sep 28 '20 11:09 79percent

用reduce来实现

let a= [[1,2,[3]],[4,5,[6,[[7],8]],9]]
const flatten = (arr) => {
    return arr.reduce((pre, item) => {
        return pre.concat(Array.isArray(item) ? flatten(item) : item)
    },[])
}
console.log(flatten(a))

JeremyChenn avatar Jan 06 '21 02:01 JeremyChenn

迭代实现

function flatten(arr) {
  const result = []
  let target = arr

  while (Array.isArray(target)) {
    const copy = target.slice()
    for (let i = 0; i < copy.length; i += 1) {
      target = copy[i]
      if (!Array.isArray(copy[i])) {
        result.push(copy[i])
      }
    }
  }
  return result
}

递归实现

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

pan-Z2l0aHVi avatar Jan 25 '21 10:01 pan-Z2l0aHVi

String(arr).split(',').map(Number)

koujialong avatar Feb 25 '21 03:02 koujialong

const a = [1,2,3,[4,5,6,[7,8]]]

// 递归
const flatten = (arr) => {
  return arr.reduce((sum,curr) => {
    return sum.concat(Array.isArray(curr) ? flatten(curr) : curr);
  },[])
}

// 迭代
const iterativeFlatten = (arr) => {
  const stack = [];
  const rlt = [];
  stack.push(arr);
  while(stack.length){
    while(Array.isArray(stack[stack.length - 1])){
      const temp = stack.pop();
      for(let i = temp.length-1; i>=0; i++){
        stack.push(temp[i]);
      }
    }
    rlt.push(stack.pop());
  }
  return rlt;
}

miyukoarc avatar Mar 10 '21 09:03 miyukoarc

三种方式

//  toString()
var flatten = (arr) => {
  return arr.toString().split(',').map(Number)
}

// 递归
var flatten = (arr) => {
  var ret = []
  arr.forEach(item => {
    var temp = Array.isArray(item) ? flatten(item) : [item]
    ret.push(...temp)
  })
  return ret
} 

// 迭代
var flatten = (arr) => {
  if(!arr.length) {
    return []
  }

  var ret = []
  var queue = [arr]
  while(queue.length) {
    var cur = queue.shift()
    if (Array.isArray(cur)) {
      queue.unshift(...cur)
    } else {
      ret.push(cur)
    }
  }
  
  return ret
} 

MrLeihe avatar Apr 24 '21 13:04 MrLeihe

function flatten(arr) {
    const items = [].concat(arr) // 拷贝数组防止直接操作原数组
    const res = [] // 创建新的数组
    while (items.length) { // 如果拷贝的数组还有数据
        const item = items.shift() // 弹出第一个数据
        if (Array.isArray(item)) { // 如果弹出的是一个数组
            items.unshift(...item) // 那么推入
        } else { 
            res.push(item) // 推入返回的数组
        }
    }
    return res
}

ruanlinxin avatar May 05 '21 10:05 ruanlinxin

使用栈将element反复推入拍平数组

let flatten = arr => {
    const newArr = [];
    let cur = null;
    while(cur = arr.pop()) {
        if (Array.isArray(cur)) {
            arr.push(...cur)
        } else {
            newArr.push(cur)
        }
    }
    return newArr.reverse()
}

lee88688 avatar May 06 '21 13:05 lee88688

ES6实现无限层级的flatten

const flatten = arr => arr.reduce((acc, cur) => (
    Array.isArray(cur) 
   ? [...acc, ...flatten(cur)]
   : [...acc, cur]
), []);

进一步优化一下,带有depth参数

const flattenBydepth = (arr, depth = 1) => 
    depth > 1
        ? arr.reduce((acc, cur) => Array.isArray(cur) 
            ? [...acc, ...flattenBydepth(cur, depth -1)] 
            : [...acc, cur], [])
        : arr.reduce((acc, cur) => [...acc, cur], []);

sunnala avatar Jun 02 '21 04:06 sunnala

惭愧这么个简单的功能居然写了快50行。。。不过带上了对depth的处理,抛砖引玉吧

const iterationFlatten = (arr,depth=1)=>{
    if (!Array.isArray(arr)) {
        return [];
    }

    if (depth <= 0) {
        depth = 1;
    }

    // 存放结果
    const result = [];
    // 当前迭代深度
    let currentDepth = 0;
    // 对应深度中,当前进行迭代的索引(因为能够进行迭代的必然是数组)
    const layerIterationIndex = [0];
    // 对应深度中,当前正在进行迭代的数组对象
    let targetStack = new Array();

    targetStack.push(arr);

    while (layerIterationIndex[0] !== arr.length) {
        // 本次迭代的元素所在的数组
        const layerElement = targetStack[currentDepth];
        // 本次迭代的元素 
        const target = layerElement[layerIterationIndex[currentDepth]];
        // 本层迭代是否应该继续(数组已经迭代完毕,或者当前深度超出depth指定的值)
        const endOfThisLayer = (layerIterationIndex[currentDepth] === (layerElement.length)) || (currentDepth > depth);

        if (endOfThisLayer) {
            // 如果超出depth指定的值,则将本层元素直接放进结果            
            if (currentDepth > depth) {
                result.push(layerElement);
            }

            // 层数-1 上层迭代索引+1(因为上一层迭代中,本元素已经迭代完毕)
            currentDepth--;
            layerIterationIndex[currentDepth]++;
            
            // 弹出本层迭代元素,以及迭代索引
            layerIterationIndex.pop();
            targetStack.pop();
        } else {
            // 如果本次迭代的元素是数组,则以本元素进行深一层迭代,将本此迭代元素入栈,迭代索引入栈,初始化为0
            if (Array.isArray(target)) {
                targetStack.push(target);
                currentDepth++;
                layerIterationIndex.push(0);
            } else {
                // 如果不是数组,则直接放入结果数组,并且本层迭代索引+1
                result.push(target);
                layerIterationIndex[currentDepth]++;
            }
        }
    }

    return result;
}

// (5) [1, 2, 3, 4, Array(3)]
console.log(iterationFlatten([1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]))
// (7) [1, 2, 3, 4, 5, 6, Array(3)]
console.log(iterationFlatten([1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]], 2))
// (10) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(iterationFlatten([1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]], Infinity))

mygod48 avatar Oct 26 '21 05:10 mygod48

``function myflatten(arr, deep) { let result = []; let temp1 = arr;//当前用来遍历的数组 let temp2 = [];//保存下一次用来遍历的数组

    while (deep) {
        //如果元素是数组就放到temp2里面去,不是就放到result里
        for (let i = 0; i < temp1.length; i++) {
            if (temp1[i] instanceof Array) {
                temp2.push(...temp1[i]);
            } else {
                result.push(temp1[i]);
            }
        }
        deep--;
        //到达深度后要把没遍历的数组放到result里
        if (deep == 0) {
            result.push(...temp2);
        } else {
        temp1 = temp2;
        temp2 = [];
    }
}
return result;`

gagadGG avatar Oct 29 '21 01:10 gagadGG

//应该是迭代次数较少,而且比较方便的方法 function flatten(arr) { if(!(arr instanceof Array)){ return } var result = [], temp = [],head; if(arr.length <= 0) { return result; } temp.push(arr); while (temp.length) { head = temp.shift(); //元素是数组 if (head instanceof Array) { for (let i = 0; i < head.length; i++) { if (!(head[i] instanceof Array)) { result.push(head[i]); } else { temp.push(head[i]) } } } else { result.push(head) } } return result; }

kingforever avatar Nov 06 '21 14:11 kingforever

迭代的实现:

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

const flatten = function (arr) {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr)
    }
    return arr
}

console.log(flatten(arr))

递归的实现(ES6简写):

const flatten = array => array.reduce((acc, cur) => (Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur]), [])

卧槽concat居然有这功能,只写过拼数组,单个元素也能拼厉害了, [ ].concat(1,2,[3]) == [1,2,3]

yaoocheng avatar Nov 11 '21 07:11 yaoocheng

function flatten(arr) {
    let i = 0;
    while(i < arr.length) {
        if(Array.isArray(arr[i])) {
            var len = arr[i].length;
            arr.splice(i, 1, ...arr[i]);
        } else {
            i++;
        }
    }
    return arr;
}

chiic avatar Nov 23 '21 14:11 chiic

function flat(target) {
  let arr = [];
  target.forEach((element) => {
    if (Array.isArray(element)) arr.push(...flat(element));
    else arr.push(element);
  });
  return arr;
}
let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]];
console.log("结果", flat(arr));

Four-Names avatar Feb 22 '22 09:02 Four-Names

var arr=[1,2,3,[4,5],[6,[7,[8]]]] function flatten(arr){ return arr.reduce((pre,cur)=>{ return pre.concat(Array.isArray(cur)?flatten(cur):cur) },[]) } var newArr = flatten(arr) console.log(newArr) // [1,2,3,4,5,6,7,8]

dongwei200079 avatar Feb 25 '22 06:02 dongwei200079

迭代啊,不要用递归。

jianxing-xu avatar Mar 11 '22 05:03 jianxing-xu

迭代的实现:

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

const flatten = function (arr) {
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr)
    }
    return arr
}

console.log(flatten(arr))

递归的实现(ES6简写):

const flatten = array => array.reduce((acc, cur) => (Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur]), [])

使用 reduce 也属于迭代吧?

recude内调用flatten自身

Yuweiai avatar Jul 13 '22 06:07 Yuweiai

存收到,谢谢!

kingforever avatar Jul 13 '22 06:07 kingforever

从语义的角度,递归实现是否用forEach更好,另reduce实现:

function flatten(arr) {
  return arr.reduce((acc, cur) => {
    if(Array.isArray(cur)) {
      acc.push(...flatten(cur))
    } else {
      acc.push(cur)
    }

    return acc
  }, [])
}

Yuweiai avatar Jul 13 '22 06:07 Yuweiai

从语义的角度,递归实现是否用forEach更好,另reduce实现:

function flatten(arr) {
  return arr.reduce((acc, cur) => {
    if(Array.isArray(cur)) {
      acc.push(...flatten(cur))
    } else {
      acc.push(cur)
    }

    return acc
  }, [])
}
// 返回数组的维数(虽然没用到)
function arrDimension(arr) {
  return arr.length ? Math.max(...arr.map(item => Array.isArray(item) ? arrDimension(item) + 1 : 1)) : 1
}

function flatten(arr, depth = 1) {
  if(depth === 0) return arr

  return arr.reduce((acc, cur) => {
    if(Array.isArray(cur)) {
      acc.push(...flatten(cur, depth - 1))
    } else {
      acc.push(cur)
    }

    return acc
  }, [])
}

Yuweiai avatar Jul 13 '22 06:07 Yuweiai