Jess
Jess

Reputation: 253

Flattening nested array in JavaScript

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!

Upvotes: 11

Views: 11006

Answers (10)

Maneesh Reddy
Maneesh Reddy

Reputation: 11

Implement flatten function using recursion and spread operator.

const a = [1,[2,[3,4],[5]],6];
const flatten = (arr) => {
    const res = []
    for(let i=0;i<arr.length;i++) {
        if(!Array.isArray(arr[i])) res.push(arr[i]);
        else res.push(...flatten(arr[i]));
    }
    return res;
}
console.log(flatten(a));

Upvotes: 1

Shubham Bansod
Shubham Bansod

Reputation: 1

let arr = [1,2,[3,4]]

/* let newarr = arr.flat(); */

let newarr = Object.values(arr);
let arr2 = []
for(let val of Object.values(arr)) {
         if(!Array.isArray(val)){
     console.log(val)
     arr2.push(val)
     }    
           for ( let val2 of Object.values(val)){
             arr2.push(val2)
           }
}
console.log(arr2)

Upvotes: 0

Rick Edwards
Rick Edwards

Reputation: 67

No one thought of splicing in-place?

function flatten(array){
    for (var i = 0; i < array.length; i++) {
        if(array[i] instanceof Array){
            array.splice.apply(array,[i,1].concat(array[i]));
            i--;
        }
    };
    return array;
}

One iteration, no recursion.

Upvotes: 1

Peter Eskandar
Peter Eskandar

Reputation: 79

function steamrollArray(arr) {
  var tmp = [];
  arr.forEach(function(val){
    if(Array.isArray(val))
      tmp = tmp.concat(steamrollArray(val));
    else
      tmp.push(val);
  });

  console.log(tmp);
  return tmp;
}

steamrollArray([1, [2], [3, [[4]]]]);

Upvotes: 0

user93
user93

Reputation: 1866

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]

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386570

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

Upvotes: 9

Nenad Vracar
Nenad Vracar

Reputation: 122047

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]), [])

Upvotes: 8

Naghaveer R
Naghaveer R

Reputation: 2944

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

Upvotes: 1

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

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

Upvotes: 2

Luan Nico
Luan Nico

Reputation: 5917

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.

Upvotes: 9

Related Questions