Live data from Hacker News

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

wisdomgeek.com

51–60 of 97 posts

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

#52

Earlier quoted context omitted.

added this to the post as well, a place where there is an array inside an array of objects and you want all those. For example, if we want to extract all roles from the array: [ { name: "Saransh Kataria" , roles: ['system-admin', 'developer'] }, { name: "Wisdom Geek" , roles: ['basic'] }, ].flatMap(x => x.roles); // Output => ["admin", "system-admin", "developer"]

wouldn't the output be ['basic', 'system-admin', 'developer'] rather than array[0] being 'admin'?

you are right, I was trying to format it for HN but somehow screwed up copy pasting, though it'd be ["system-admin", "developer", "basic"] and not ['basic', 'system-admin', 'developer']

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

#54

A lot of funtional primitives have really counterintuitive names for me. flatMap is one of them.

agreed, though I doubt there's anything we can do about it.

In F# we call it 'collect' instead, partially for this reason.

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

#55

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've discovered transducers (which I think have a rather horrible and confusing for newcomers higher-order function presentation in the language that popularized them, i.e. Clojure, when they could just be lists)! All transducers are is a function `x -> List(x)` and then you can use other functions such as `flatMap` to apply them (as your example illustrates nicely this is why map, filter, and its combination can all be described as single transducers).

You do have to make sure that your implementation of list is extremely efficient on zero and one element lists (ideally it generates no garbage at all in those cases) otherwise as other commentators have pointed out you'll have a lot of GC pressure.

And even though the transducer itself is `x -> List(x)` note that the `List` is only produced as an intermediate step and doesn't need to exist in the final product. You could apply a `x -> List(x)` to a generator for example and just "absorb" the list back into the resulting generator.

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

#56
post #48
post #29

Earlier quoted context omitted.

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…

I just filed this issue on the MDN page: https://github.com/mdn/content/issues/11763 That note is misleading.

It still creates a temporary [x, 2*x] array for every element though. This is an unavoidable problem with flatMap, while reduce can easily be changed to reuse the same accumulator array, making it twice as fast as flatMap and almost as fast as the simple for-loop approach.

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

#57

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…

Yes, but you could also use `fold`^H^H^H^H`reduce`. [1, 2, 3, 4, 5].reduce((acc, n) => n % 2 === 1 ? acc.push(2*n) : acc, [])

What is `f`reduce`?

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

#58
post #30
post #14

Earlier quoted context omitted.

> What is a realistic scenario where an array needs to be flattened? Concatenating the result of a paginated API. Showing all the objects two or more 1:N steps away from you in the object graph. The events your friends are attending, the issues your coworkers are working on, the people belonging to any of your same groups. Basically any time you would do a SELECT... JOIN in SQL.

If you’re doing that aren’t you kinda defeating the point of pagination? Paginated APIs to me are a contract that says the size of the results can be arbitrarily large and there be dragons if you try to fit them in memory. With how many wrappers around paginated APIs to unpaginate them I must be wrong but it still bugs me.

Sometimes the pagination is optional to allow the client to only get as many results as they can handle.

But far more often, the pagination is forced - get 100 results, hit this link for the next 100 - in order to limit the load on the server.

Most trivial scenario, client runs a search that's too generic, you don't want to waste server resources actually preparing 999999 results.

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

#59
post #7

I've made it a habit to check Mozilla's JS docs once in a while for functions like Flat() and FlatMap(). Sometimes if I find myself reaching for underscore/lodash, I'll check Mozilla docs first to see if there's some new function that can let me omit using lodash. I'm often delighted to find new convenience functions I can just use without adding another dependable.

I often use Lodash’s sumBy, groupBy and orderBy. Love the versatility and one-liner aspect. E.g. sumBy(“orders”, “total.amount”)

Which input method are you using that double quotes are ” (U+201C) instead of " (U+0022)?

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

#60

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…

Or… use reduce.
Post reply on HN