TechnoCorner
TechnoCorner

Reputation: 5135

Flatten javascript multi dimentional nested array

I am trying to flatten an array but I'm having difficulties.

My code:

    var arr = [["2"],["3", "4"], "5", [["6"], ["7"]] ];
    
    var res = [].concat.apply([], arr);
    
    //Using reduce(ES5)

   function test(args){
     var sum = args.reduce(function(acc, val){
       acc.concat(Array.isArray(val)? test(val): val);
     });
    }

    //Regular implementation
    function test2(arr){
      var result = [];
      arr.forEach(function(val){
        if(Array.isArray(val)){
          result = [].concat.apply([], val);
        } else {
          result.concat(val);
        }
      });
      return result;
    }
    
    console.log(test(arr));
    console.log(test2(arr));

Expected Output:

["2", "3", "4","5", "6", "7"]

Can someone enlighten me where I'm going wrong?

Upvotes: 1

Views: 137

Answers (4)

f-CJ
f-CJ

Reputation: 4481

var arr = [["2"],["3", "4"], "5", [["6"], ["7"]] ];

var flatten = arr.flat(Infinity);

console.log(flatten);

Since Array.prototype.flat() has been included in the standard ECMAScript 2019 (ES10), there is no need to implement your own methods to flatten arrays.

The flat method can take a parameter to specify how deep a nested array structure should be flattened. In the above example I'm passing the global scope variable Infinity so it flattens all the levels.

At the time of writing (04/11/2019) all major browsers except Edge have implemented the feature in their newer versions. Babel 7.4.0 (with core-js@3) also comes with it.

Upvotes: 1

Sagar V
Sagar V

Reputation: 12478

Thats it. So simple

var arr = [["2"], ["3", "4"], "5", [["6"], ["7"]]];

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

console.log(test2(arr));

Upvotes: 5

Rajesh
Rajesh

Reputation: 24915

Since its a nested structure, you should use recursion

Logic

  • Loop over passed array and check if current item is an array.
  • If yes, repeat the process.
  • If not, push value to temp array.
  • Merge return value of each recursion to previous one.

Array.forEach

var arr = [["2"],["3", "4"], "5", [["6"], ["7"]] ];

function getFlattenArray(array){
  var _tmp = [];
  array.forEach(function(item){
    if(Array.isArray(item)) {
      _tmp = _tmp.concat(getFlattenArray(item))
    }
    else{
      _tmp.push(item);
    }
  })
  return _tmp;
}

var result = getFlattenArray(arr);

console.log(result)

Array.reduce

var arr = [["2"],["3", "4"], "5", [["6"], ["7"]] ];

function getFlattenArray(array){
  return array.reduce(function(p,c){
    if(Array.isArray(c)) {
      p = p.concat(getFlattenArray(c))
    }
    else{
      p.push(c);
    }
    return p
  }, [])
}

var result = getFlattenArray(arr);

console.log(result)


ES6 Version

var arr = [["2"],["3", "4"], "5", [["6"], ["7"]] ];

function getFlattenArray(array){
  return array.reduce((p,c) => (Array.isArray(c) ? p=p.concat(getFlattenArray(c)) : p.push(c) ) && p, [])
}

var result = getFlattenArray(arr);

console.log(result)

Upvotes: 4

Jhecht
Jhecht

Reputation: 4435

I think the reason the code I linked you wasn't working was that you probably made the same error I did. I believe (don't really care to look it up, someone will correct me if I am wrong) that arrow functions automatically return the last line, so when turning the code into ES5 you forget to return the arr.reduce(...).

This works for me, Chrome on Windows.

var arr = [
  ["2"],
  ["3", "4"], "5", [
    ["6"],
    ["7"]
  ]
];

function flatten(arr) {
  return arr.reduce(function(acc, val) {
    return acc.concat(Array.isArray(val) ? flatten(val) : val);
  }, []);
}

console.log(flatten(arr));

Upvotes: 1

Related Questions