24

I'm trying to find an elegant way in Coffeescript to merge an array of arrays, so that [[1,2,3],[4,5,6],[7,8,9]] ==> [1,2,3,4,5,6,7,8,9].

As you might imagine, I need this because I'm generating arrays from a function in a "for in" construct and need to concatenate the resulting nested array:

result = (generate_array(x) for x in arr)

Is there an elegant way to handle this? Thanks for any pointers!

5 Answers 5

49

Just use the JS idiom:

 [].concat.apply([], a)

which becomes a little nicer in Coffee:

$ coffee -e 'a = [[1,2,3],[4,5,6],[7,8,9]]; console.dir [].concat a...'
[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Sign up to request clarification or add additional context in comments.

3 Comments

that idiom is brilliant- Thanks for making me aware of it!
For those like me who don't get it right away, the second argument of apply is a list where each item in the list becomes an argument passed to the function. So for [[1,2,3],[4,5,6],[7,8,9]] you are essentially calling [].concat([1,2,3],[4,5,6],[7,8,9]).
Word of warning - if your array is sufficiently large (perhaps millions of elements?), you can cause a stack overflow.
5

OK, one way is to include the underscore.js library. It is a very nice, lightweight but powerful utility library, and it has _.flatten which does exactly this.

Barring that, you could take the underscore.js code for flatten and modify it to remove any other underscore dependencies to create your own standalone "flatten".

Here's the underscore.js "_.flatten" code:

 _.flatten = function(array) {
   return _.reduce(array, function(memo, value) {
     if (_.isArray(value)) return memo.concat(_.flatten(value));
     memo[memo.length] = value;
     return memo;
   }, []);
 };

Notice that it is doing some nice stuff for you. For example, many of the underscore functions like _.reduce will check to see if the browser has implemented a native version, which some have. If so, it will use the native which of course runs much faster. The _.isArray implementation does the same thing.

Comments

5

What about this for Coffee

[[1, 2, 3], [4, 5, 6], [7, 8, 9]].reduce (a, b) ->
  a.concat b

or this for pure Javascript

[[1, 2, 3], [4, 5, 6], [7 , 8, 9]].reduce((a, b) => a.concat(b));

1 Comment

.reduce (a, b) -> [a..., b...] is coffier
0

sugarjs is another elegance way to do it:

[[1, 2, 3]].flatten() //=> [1, 2, 3]

sugarjs: flatten

Comments

-3

Why not try using Lodash?

_.flatten([1,2,3], [4,5,6]) => [1,2,3,4,5,6]

https://lodash.com/docs#flatten

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.