1

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?

7
  • Check out this link Commented Feb 17, 2017 at 7:12
  • @Jhecht i did try that intitally, but it was written in ES6. I have added my ES5 version but am not sure what am i doing wrong over there. It's giving me undefined. Commented Feb 17, 2017 at 7:15
  • Possible duplicate of Merge/flatten an array of arrays in JavaScript? Commented Feb 17, 2017 at 7:18
  • @Andreas Not sure if this is exact duplicate as OP is referring to nested structure. [[[]], [[]]] and not [[],[],[]] Commented Feb 17, 2017 at 7:28
  • @Rajesh stackoverflow.com/a/15030117/402037 -> flatten([[[1, [1.1]], 2, 3], [4, 5]]); // [1, 1.1, 2, 3, 4, 5] Commented Feb 17, 2017 at 7:30

4 Answers 4

5

Thats it. So simple

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

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

console.log(test2(arr));

Sign up to request clarification or add additional context in comments.

3 Comments

ahh, clever approach, should be the accepted answer.
Only works with arrays of strings without commas. Does not work for [{foo: 1}, [{age: 2}, {foo: 3}]] or ['a string, has commas']
i answered for OP's question. There are different scenarios. As JavaScript runs on browser, each line of code is more important to keep efficiency. In this scenario, this line is most efficient.
4

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)

1 Comment

damn.. thanks so much. This was helpful! .. Can you also give me a solution with Array.reduce?
1

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));

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.