Live data from Hacker News

Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

wisdomgeek.com

31–40 of 97 posts

Re: Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

#31

I've always found `flatMap` to be interesting because it feels like a convenience function, combining .map(fn).flat() into one function. It's interesting because JS doesn't really have a lot of convenience functions that are this shallow (ie. that provide just minimal cleanup compared to the functions they're wrapping). Is there some specific reason that `flatMap` made the cut?

Small mistake, and maybe that's why this function exists, but it's actually combines `.map(fn).flat(1)`. I think conceptually, `flatMap` is a `map` where each iteration can return multiple values (or none). So it feels quite more powerful than just `map` and is a quite common convenience function.

I think the depth argument of flat defaults to 1, so it'd be the same anyway. Not sure why the default is 1, I'd prefer Infinity so it'd always flatten everything by default, but maybe there are some good reasons for it.

Re: Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

#32
post #29

Something that people may not see immediately is that flatMap is more general than map and filter. Say, for a contrived example, that you'd like to filter out the even numbers in an array, and then double the odd numbers that remain. Instead of: [1, 2, 3, 4, 5].filter(n => n % 2 === 1).map(n => n * 2) You can do: [1, 2, 3, 4, 5].flatMap(n => n % 2 === 1 ? [n * 2] : []) Again, this is a contrived example, but I think…

For those wondering at home, the reason you shouldn't do this is immediately spelled out in the Mozilla docs for flatMap: > Note, however, that this is inefficient and should be avoided for large arrays: in each iteration, it creates a new temporary array that must be garbage-collected, and it copies elements from the current accumulator array into a new array instead of just adding the new elements to the existing a…

Sure. I'm not suggesting it be used to this effect; I'm noting the generality as an interesting point.

Re: Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

#33
This stirs up some memories of Perl, where flattening arrays/lists is the default, and you need explicit references to have nested arrays or hash tables. I remember it used to be a kind of foot-seeking gun for newbies, but I never ran into trouble with it once I understood references (which isn't super hard).

Re: Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

#34

Earlier quoted context omitted.

Push returns the length of the array, though, so that won't work.

Ah, sorry, so you have to concat the arrays using `concat`. [1, 2, 3, 4, 5].reduce((acc, n) => n % 2 === 1 ? acc.concat([2*n]) : acc, [])

Wouldn't recommend doing this - if the original array is of significant length this'll get quite slow because `acc.concat` has to create a brand new array of slightly longer length on each iteration it's called. Better to just use `push` like you suggested before and then return the array if you want to use `reduce`.

Re: Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

#35

Earlier quoted context omitted.

Ah, sorry, so you have to concat the arrays using `concat`. [1, 2, 3, 4, 5].reduce((acc, n) => n % 2 === 1 ? acc.concat([2*n]) : acc, [])

Wouldn't recommend doing this - if the original array is of significant length this'll get quite slow because `acc.concat` has to create a brand new array of slightly longer length on each iteration it's called. Better to just use `push` like you suggested before and then return the array if you want to use `reduce`.

Yes, of course, that's why I used `push` at first.

Re: Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

#36

Something that people may not see immediately is that flatMap is more general than map and filter. Say, for a contrived example, that you'd like to filter out the even numbers in an array, and then double the odd numbers that remain. Instead of: [1, 2, 3, 4, 5].filter(n => n % 2 === 1).map(n => n * 2) You can do: [1, 2, 3, 4, 5].flatMap(n => n % 2 === 1 ? [n * 2] : []) Again, this is a contrived example, but I think…

I'm not sure it's any more general considering that you have to return an array and also treat an empty array as a 'null' value.

Or to put it another way, if I reviewed code where someone used flatMap for anything other than lists of lists I'd be likely to suggest filter/map or reduce or some other convenient equivalent depending on the purpose of the code.

Something like Ruby's filter_map[0] would do the job, although not with this particular example (because 0 is truthy in Ruby).

[0] https://ruby-doc.org/core-3.1.0/Enumerable.html#method-i-fil...

Re: Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

#37

Something that people may not see immediately is that flatMap is more general than map and filter. Say, for a contrived example, that you'd like to filter out the even numbers in an array, and then double the odd numbers that remain. Instead of: [1, 2, 3, 4, 5].filter(n => n % 2 === 1).map(n => n * 2) You can do: [1, 2, 3, 4, 5].flatMap(n => n % 2 === 1 ? [n * 2] : []) Again, this is a contrived example, but I think…

You could do that, but I’d argue using filter then map is more readable. What do empty arrays have to do with doubling even integers?

The interesting generalization is that once you realize that flatMap lets you map and filter at the same time is that you can generate arbitrary elements in the output list corresponding to each item in the input list. For example,

    ls.flatMap(x => {
      if (x 
gives you all the real square roots from the original list, doing the mapping, flattening, and filtering all in one function call.

Re: Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

#38

Something that people may not see immediately is that flatMap is more general than map and filter. Say, for a contrived example, that you'd like to filter out the even numbers in an array, and then double the odd numbers that remain. Instead of: [1, 2, 3, 4, 5].filter(n => n % 2 === 1).map(n => n * 2) You can do: [1, 2, 3, 4, 5].flatMap(n => n % 2 === 1 ? [n * 2] : []) Again, this is a contrived example, but I think…

In addition to being essentially a combined "filter" and "map", it's also a "better" filter than filter itself in TypeScript in such that it narrows types much more ergonomically[0].

In TypeScript, you might have an array of multiple types (e.g. `Array`), and use a `filter` call to only keep the `A`s. However, in many situations TypeScript can't figure this out and the resulting array type is still `Array`. However, when you just use `flatMap` to do nothing more than filtering in the same way, TypeScript can determine that the resulting type is just `Array`. It's a bit unfortunate really - `filter` is faster and more readable, but the ergonomics of `flatMap` type-wise are so much nicer! Just some interesting trivia.

[0]: https://github.com/microsoft/TypeScript/issues/16069#issueco...

Re: Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

#39
I'm glad JS is adding these methods to Array. It would be nice if iterables had similar methods for working with lazy sequences, similar to Rust, but this isn't practical since "iterable" is a protocol. Array can do it because it's a class. Perhaps JS could also adopt something similar to Rust's traits, such that implementing the protocol would make a set of related methods callable on that object.

Re: Flatten Arrays in Vanilla JavaScript with Flat() and FlatMap()

#40

Something that people may not see immediately is that flatMap is more general than map and filter. Say, for a contrived example, that you'd like to filter out the even numbers in an array, and then double the odd numbers that remain. Instead of: [1, 2, 3, 4, 5].filter(n => n % 2 === 1).map(n => n * 2) You can do: [1, 2, 3, 4, 5].flatMap(n => n % 2 === 1 ? [n * 2] : []) Again, this is a contrived example, but I think…

You could do that, but I’d argue using filter then map is more readable. What do empty arrays have to do with doubling even integers?

I agree on the readability. There's a TC proposal floating around for a pipeline operator. I don't think it's moved but that would be a game changer.
Post reply on HN