Home > Back-end >  Concat works but push doesn't while flattening array
Concat works but push doesn't while flattening array

Time:09-07

Following code works fine to flatten deeply nested array

const arr = [[2, [4, 9]], 6, [5,32]];;
const finalArr = [];

function flattenArr(currArr) {
  for (var el of currArr) {
    if (Array.isArray(el)) {
      finalArr.concat(flattenArr(el));
    } else {
      finalArr.push(el);
    }
  }
  return finalArr;
}
flattenArr(arr);
console.log(finalArr); // Output:[2, 4, 9, 6, 5, 32]

But if I replace concat with push, it breaks and gives the following output:

[2, 4, 9, [circular object Array], [circular object Array], 6, 5, 32, [circular object Array]]

Can anyone help me understand why? Also, what does [circular object Array] mean?

CodePudding user response:

First, I want to point out that the concat in your first code is effectively doing nothing. Concat creates a new array and returns that array, but you're not using the returned array. So if you replace finalArr.concat(flattenArr(el)); with flattenArr(el); your code will still work.

const arr = [[2, [4, 9]], 6, [5,32]];
const finalArr = [];

function flattenArr(currArr) {
  for (var el of currArr) {
    if (Array.isArray(el)) {
      flattenArr(el)
    } else {
      finalArr.push(el);
    }
  }
  return finalArr;
}
flattenArr(arr);
console.log(finalArr); // Output:[2, 4, 9, 6, 5, 32]

But when you switch it to .push, push does do something. It's going to insert into the existing finalArr array. And the thing it's going to insert is whatever's returned by flattenArr(el), which is finalArr. So you're pushing the array into itself, which ends up with circular references (the array contains itself, which contains itself, which contains itself, etc), and that's why some consoles will log it as [circular object Array].


The core issue you have is that you only ever use one array for computing the output: the array named finalArr, which you define on line 2. That is one way to solve array flattening, as your first code demonstrates. But if you prefer to do it by recursively flattening subarrays, and then combining them with push (or concat), then each time you recurse, you need to make a new array.

A second issue is that when you do the .push, you need to pass the individual items of the array as separate arguments, not the entire array as one argument. This can be done with spread syntax (...).

For example:

const arr = [[2, [4, 9]], 6, [5,32]];

function flattenArr(currArr) {
  const result = []; // Creating a brand new array
  for (var el of currArr) {
    if (Array.isArray(el)) {
      result.push(...flattenArr(el)); // Note that i used spread syntax here
    } else {
      result.push(el);
    }
  }
  return result;
}
const finalArr = flattenArr(arr);
console.log(finalArr);

  • Related