Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I have a horrible looking array which looks like this:

EDIT:

array = [
    {
        Letters: [{ Letter: 'A' }, { Letter: 'B' }, { Letter: 'C' }],
        Numbers: [{ Number: '1' }, { Number: '2' }, { Number: '3' }]
    },
    null,
    {
        Letters: [{ Letter: 'D' }, { Letter: 'E' }, { Letter: 'F' }, { Letter: 'G' }, { Letter: 'H' }],
        Numbers: [{ Number: '4' }, { Number: '5' }, { Number: '6' }, { Number: '7' }]
    }
];

And want the array to look like this:

flattenedArray = [a,b,c,1,2,3,d,e,f,g,h,4,5,6,7]

Unfortunately I cannot change the original formatting because that is the form received when merging two API responses that I am getting.

I have tried using:

var flattenedArray = [].concat.apply([], array);

But it just presents the array in the same format it was entered in.

I was wondering if anybody had any advice?

EDIT: I have tried implementing the suggestions given - thank you so much for your help. It seems it is a problem with the format of the list - unfortunately using the chrome console which is in a 'tree' format I cannot see the direct structure of the array output.

Thank you for all your help! EDIT 2: See above for the actual array, thank you for showing me how to see this!

share|improve this question
1  
That's not exactly valid JS array syntax. Was this just a misrepresentation in your question, or is it actually a string you are receiving that looks exactly like this? – Bergi 15 hours ago
    
I'm not sure what the string exactly looks like, it is how I interpretted it looking from the developer tools on chrome. I can't figure out how to stop it presenting the information as a tree but it looks more like: – Jess 14 hours ago
1  
Then please show us (edit it into your question) the output that console.log(JSON.stringify(array)) generates. Getting a tree view suggests that you are not having a plain string – Bergi 14 hours ago
2  
Oh well, that's actually not just a nested array but a nested array of objects. Which invalidates all the answers :-( – Bergi 14 hours ago
1  
@jess, now you have to treat the objects as well as the arrays. What do you want with null? – Nina Scholz 13 hours ago
up vote 4 down vote accepted

Edit for the new request of nested arrays/objects and the flattening, you could use a combined approach with testing for the type of an element.

var array = [{ Letters: [{ Letter: 'A' }, { Letter: 'B' }, { Letter: 'C' }], Numbers: [{ Number: '1' }, { Number: '2' }, { Number: '3' }] }, null, { Letters: [{ Letter: 'D' }, { Letter: 'E' }, { Letter: 'F' }, { Letter: 'G' }, { Letter: 'H' }], Numbers: [{ Number: '4' }, { Number: '5' }, { Number: '6' }, { Number: '7' }] }],
    result = array.reduce(function iter(r, a) {
        if (a === null) {
            return r;
        }
        if (Array.isArray(a)) {
            return a.reduce(iter, r);
        }
        if (typeof a === 'object') {
            return Object.keys(a).map(k => a[k]).reduce(iter, r);
        }
        return r.concat(a);
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Old request and the immortal question how to flat a nested array.

var flat = (r, a) => Array.isArray(a) ? a.reduce(flat, r) : r.concat(a),
    inputArray = array = [[['a', 'b', 'c'], [1, 2, 3]], [], [['d', 'e', 'f', 'g', 'h'], [4, 5, 6, 7]]],
    outputArray = inputArray.reduce(flat, []);

console.log(outputArray);

share|improve this answer
2  
Just tested it out and it works a charm - thank you for taking the time to help! – Jess 13 hours ago

If you have lodash, you can use:

_.flattenDeep(array)

You can also checkout their source code for ides on how to implement yourself if you prefer.

share|improve this answer

You can create recursive function using forEach() that will return new array.

var array = [[['a','b','c'],[1,2,3]],[],[['d','e','f','g','h'],[4,5,6,7]]]
function flat(data) {
  var r = []
  data.forEach(e => Array.isArray(e) ? r = r.concat(flat(e)) : r.push(e));
  return r;
}

console.log(flat(array))

You can also use reduce() instead of forEach()

var array = [[['a','b','c'],[1,2,3]],[],[['d','e','f','g','h'],[4,5,6,7]]]

function flat(data) {
  return data.reduce((r, e) => Array.isArray(e) ? r = r.concat(flat(e)) : r.push(e) && r, [])
}

console.log(flat(array))

As @Bergi suggested you can use reduce() like this.

data.reduce((r, e) => r.concat(Array.isArray(e) ? flat(e) : [e]), [])
share|improve this answer
    
&& r will kill readability. I'm sure many people will not understand purpose of it. I'd suggest splitting code into 2 lines and using return r instead – Rajesh 16 hours ago
    
s/can/should/ use reduce. If you want imperative iteration, use a for…of loop instead of forEach with an arrow function. – Bergi 15 hours ago
1  
Btw, in the case of concat you don't need to reassign r. Better just use (r, e) => r.concat(Array.isArray(e) ? flat(e) : [e]) as the reducer. – Bergi 15 hours ago
    
@Bergi Wow that is great, just why brackets on : [e] how about data.reduce((r, e) => r.concat(Array.isArray(e) ? flat(e) : e), [])? – Nenad Vracar 14 hours ago
    
Because only arrays should be passed to concat. Plain values kinda work as well, but concat always has to check whether they are spreadable like arrays (which since ES6 is also not exactly the same any more) – Bergi 14 hours ago

It's nice to use a recursive function for such cases:

arr = [[['a','b','c'],[1,2,3]],[],[['d','e','f','g','h'],[4,5,6,7]]];

function flatten(arr) {
    var result = [];
    for (var i = 0, len = arr.length; i < len; i++) {
       result = result.concat(Array.isArray(arr[i])? flatten(arr[i]) : [arr[i]]);
    }
    return result;
}
console.log(flatten(arr));

share|improve this answer

Your Array format is not correct, you are missing commas(,). This is correct array.

var array = [[['a','b','c'],[1,2,3]],[],[['d','e','f','g','h'],[4,5,6,7]]];

var array = [[['a','b','c'],[1,2,3]],[],[['d','e','f','g','h'],[4,5,6,7]]];
var result = flatten(array);
    
function flatten(array) {
    var flat = [];
    if(array !== undefined){
    var flat = [];
    for (var i = 0; i < arguments.length; i++) {
          if (arguments[i] instanceof Array) {
            flat = flat.concat(flatten.apply(null, arguments[i]));
          } else {
            flat.push(arguments[i]);
          }
        }
      }
    return flat;
}

console.log(result);

share|improve this answer
    
I believe this code flattens just one level deep; for deeper flattening, you would need to run this recursively. Or use lodash, as I suggested ;) – Luan Nico 16 hours ago
    
@LuanNico Sorry I have updated my answer. – Nagaveer Gowda 16 hours ago

You could try the flatten function in Ramda.

  R.flatten([1, 2, [3, 4], 5, [6, [7, 8, [9, [10, 11], 12]]]]);
    //=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.