2

I am pretty new to javascript and I have an issue with flattening several arrays into one complete array using the reduce and concat function.

var array = [ [1, 3], [6, 6], [3, 3] ]; 

var finishedArray = function(array) {
var reducedArray = {};
var completeArray = {};


for (var i = 0; i < array.length; i++) {
    reducedArray[i] = array[i].reduce(function (a, b) {
        return a + b;
    });

    completeArray = reducedArray[i].concat(reducedArray[i + 1]);
}

return completeArray;

}

console.log(finishedArray(array));`

The error I get is : completeArray = reducedArray[i].concat(reducedArray[i + 1]);

TypeError: undefined is not a function

Why is that???

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
Benny
  • 839
  • 16
  • 32

4 Answers4

5

the easy way:

var finishedArray = [ [1, 3], [6, 6], [3, 3] ].reduce(Function.apply.bind([].concat), [])

another nice option than can be more readable is using a named function, which lets you apply this transform to many arrays in many places without so much ugly boilerplate every time:

function flat(a,b){return a.concat(b);}

[[1,3],[6,6],[3,3]].reduce(flat);
[[7,3],[4,6],[8,1]].reduce(flat);

it's the shortest path to flatten many different arrays.

note you can also write the reusable in the same fast-but-ugly syntax as my first suggestion:

 var flat=Function.apply.bind([].concat);

also note that elclanrs shows an even simpler method that i really like:

 [].concat.apply([],[[1,3],[6,6],[3,3]]) 
dandavis
  • 16,370
  • 5
  • 40
  • 36
  • It's even easier: As the comment below the Q says, he messed up [] vs. {}. – Mörre Jan 16 '15 at 21:59
  • 1
    @Someone: this is ES5. or js1.6 in old firefoxes. or anything with reduce and bind polyfills... – dandavis Jan 16 '15 at 21:59
  • The easy-easy way `[].concat.apply([],[[1,3],[6,6],[3,3]])` – elclanrs Jan 16 '15 at 22:02
  • 1
    I don't think more concise is necessarily easier. I would do it like this: `[[1,3],[6,6],[3,3]].reduce(function(a,b){return a.concat(b);})` – chiliNUT Jan 16 '15 at 22:04
  • Yeah, although it is probably somewhere in this dup http://stackoverflow.com/questions/10865025/merge-flatten-an-array-of-arrays-in-javascript – elclanrs Jan 16 '15 at 22:06
  • 1
    @Someone: few things are necessary, but this feels pretty old to me already. i can't wait for readbility and laziness at the same time: arr.reduce( (a,b)=>a.concat(b) ) ... – dandavis Jan 16 '15 at 22:20
3

@Dandavis has provided a perfectly good answer showing how to 'flatten' an jagged array—to turn an array of arrays into a single array containing all the elements of the original arrays. I'll try to explain why you're getting the error you are and hopefully improve your understanding of these methods.

First off, note that you declared reducedArray and completeArray as empty objects ({}). the syntax for creating an empty array is:

var reducedArray = [];
var completeArray = [];

Once you fix that though, you will still have problems. In this statement:

reducedArray[i] = array[i].reduce(function (a, b) {
    return a + b;
});

The reduce method will turn an input array (in this case array[i]) into a single value, by summing each consecutive item and returning the final result. Notice what this returns:

var array = [ [1, 3], [6, 6], [3, 3] ]; 
for (var i = 0; i < array.length; i++) {
    reducedArray[i] = array[i].reduce(function (a, b) {
        return a + b;
    });
}
console.log(reducedArray); // [4, 12, 6]

This means that reducedArray[i] is actually a number, not an array, and there is no concat method on the Number type. Because concat is undefined, you cannot call it like a function.

p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • re-considering the part about "pretty new to javascript", and in reflection, I have come to believe this is the right approach to a good answer. – dandavis Jan 16 '15 at 22:31
  • @dandavis Thanks, but I don't think you should have deleted your answer. It discusses a number of good approaches to solving the core problem, and would definitely be illustrative once OP has understood the original problems. The two answers seem to complement each other, IMO. – p.s.w.g Jan 16 '15 at 22:37
  • re-re-considering, i put it back up, it does have some decent examples. i still think an educational response is more apropos... – dandavis Jan 16 '15 at 22:47
0

We can also do this using Arrow function like:

var array = [ [1, 3], [6, 6], [3, 3] ];
var finishedArray = array.reduce((e, f) => e.concat(f), []);

 


Demo:

var array = [ [1, 3], [6, 6], [3, 3] ];
var finishedArray = array.reduce((e, f) => e.concat(f), []);

// Output
console.log( finishedArray );

This will give output like:

[1, 3, 6, 6, 3, 3]

 


If you need unique values in this finishedArray variable you can also do:

var uniqueArray = [...new Set(finishedArray)];

Demo:

var array = [ [1, 3], [6, 6], [3, 3] ];
var finishedArray = array.reduce((e, f) => e.concat(f), []);
var uniqueArray = [...new Set(finishedArray)];

// Output
console.log( uniqueArray );

This output for this is like:

[1, 3, 6]
palaѕн
  • 72,112
  • 17
  • 116
  • 136
0

There is an easier and shorter solution.

var array = [ [1, 3], [6, 6], [3, 3] ];
vat finishedArray = [].concat(...array);

Output: [1, 3, 6, 6, 3, 3].

OIRNOIR
  • 33
  • 6