Live data from Hacker News

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

wisdomgeek.com

91–97 of 97 posts

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

#91
post #68

Earlier quoted context omitted.

If you are looking for really general and powerful, then there is the mighty reduce: [1, 2, 3, 4, 5].reduce((x, y) => y % 2 === 1 ? [...x, y * 2] : x, [])

The spread operator looks cool and makes just returning the ternary operator work here but its performance implications are non-obvious (it's makin' copies). With reduce() you're really wanting something like this: [1, 2, 3, 4, 5].reduce((x, y) => { if (y % 2 === 1) x.push(y * 2); return x; }, []) I've many times wished that push() would just return the array, it would make reduce() far easier for this sort of use ca…

I guess...

  x.concat([y*2])
would return the array (but makes a duplicate)

Anyway, I find this to be a whole lot more sensible:

  x=[];
  for(y of [1,2,3,4,5]){
    if(y%2===1)x.push(y*2)
  }
Or even!

  y=[1,2,3,4,5];
  x=[];
  // map reduce/flatmap/map/filter etc omg wtf
  for( i=0; i 
I cant even tell what language this is but there is nothing here that needs fixing.

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

#92
post #90

Earlier quoted context omitted.

Minority opinion: please `let` your mutable references. I know `const` doesn’t signal immutability, but we as humans with eyeballs and limited attention span certainly benefit from knowing when a value might change at runtime.

Disagree: virtually everything in JS is mutable, so this almost means "never use the `const` keyword". Pretending that the `const` keyword means something that it doesn't makes things harder for my limited human mind to understand, not easier. Plus using `let` inappropriately makes my linter yells at me, and I usually like to just do whatever my linter tells me. Anyway, I use TypeScript, so if I really want to assert…

I `readonly` and `as const` everything I possibly can. I do know that const doesn’t mean immutable, as I said, but I think it should and I think there’s value in establishing the idiom even if it’s not currently adopted. Because otherwise const basically means nothing unless you’re mutating everything already.

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

#93
post #90

Earlier quoted context omitted.

Minority opinion: please `let` your mutable references. I know `const` doesn’t signal immutability, but we as humans with eyeballs and limited attention span certainly benefit from knowing when a value might change at runtime.

Disagree: virtually everything in JS is mutable, so this almost means "never use the `const` keyword". Pretending that the `const` keyword means something that it doesn't makes things harder for my limited human mind to understand, not easier. Plus using `let` inappropriately makes my linter yells at me, and I usually like to just do whatever my linter tells me. Anyway, I use TypeScript, so if I really want to assert…

I realize I could be clearer in what I’m asking for: please use const when you use reference types as values, and use let when you intend to mutate the reference. Using const and then changing a value is certainly allowed but it’s confusing and it’s missing an opportunity to signal in the code where changes might happen.

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

#94

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…

    /** Return this symbol to skip the current value. */
    const SKIP = Symbol("mapFilter.SKIP");
    
    /**
     * @template T, R
     * @param {T[]} array
     * @param {(SKIP: Symbol, currentValue: T, index: number, array: T[]) => R|SKIP} callback return `SKIP` to filter out an element
     * @param {number} [begin] defaults to 0
     * @param {number} [end] defaults to `array.length`
     * @returns {R[]}
     */
    function mapFilter(array, callback, begin = 0, end = array.length) {
      const ret = [];
      for (let i = begin; i 
Here. Less than ten lines without JSDoc type annotations, twenty with them. It lets you slice, map and filter all in one call without allocating intermediate arrays like you would when chaining them, making it almost as fast as a plain for-loop. It's also easy to turn it into an in-place version, removing even the array allocation overhead.

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

#97
post #67
post #42

Earlier quoted context omitted.

Surely the spread operator is nicer here? [1, 2, 3, 4, 5].reduce((acc, n) => n % 2 === 1 ? [ ...acc, 2 * n ] : acc, [])

This is not efficient. Each iteration creates a new array instance due to the spread operator.

`acc.concat()` also creates a new array instance, so I don't get your point.
Post reply on HN