Array.prototype.mapOn method

# Ahmad Bamieh (10 months ago)

Hello,

This method maps over an array of items that meet a certain condition, otherwise just pass the item as is. It is a nice feature to have along with map, filter, and other functional methods on the array prototype.

Description

Map over an array of items:

  • If the item meets the condition, apply the callback
  • If the item does not meet the condition return the item without any transformation.

Example

const exampleArray = [1, 2, 9, "C", "B", "C"];
exampleArray.mapOn(Math.sqrt, Number.isInteger); // [1, 1.414, 3, "A", "B", "C"];

Parameters

  • callback

    Function that produces an element of the new Array, taking three arguments:

    • currentValue

      The current element being processed in the array.

    • index The index of the current element being processed in the array.

    • array

      The array map was called upon.

  • condition

    Function perdicate, if returned value is truthy, the callback is applied, taking three arguments:

    • currentValue

      The current element being processed in the array.

    • index

      The index of the current element being processed in the array.

    • array

      The array map was called upon.

  • thisArg

    Optional. Value to use as this when executing callback.

Return value

A new array with each element being the result of the callback function if it meets the condition, otherwise the same item is returned.

Code/Polyfill

Array.prototype.mapOn = function(callback, condition, thisArg=this) {
  return this.map((currentValue, index, array) => {
    if(condition(currentValue, index, array)) {
      return callback.call(thisArg, currentValue, index, array)
    }
    return currentValue
  })
}

Link to Gist

gist.github.com/Bamieh/9fccbf4bc394d0da2fd0c8bb5d314476

Cheers!

Ahmad Bamieh,

# Peter Jaszkowiak (10 months ago)

Actually flatMap isn't even needed. My question is, why use this over a normal map with a conditional? It doesn't seem to really save any space.

Is there any prior art? Do a lot of people use this kind of thing in ramda, lodash, etc?

On Oct 27, 2017 09:11, "Ahmad Bamieh" <ahmadbamieh at gmail.com> wrote:

Can you elaborate?

mapOn will apply the map only if the item passes the condition, flatMap has a different use case.

I'm referring to this flatMap implementation: gist.github.com samgiles/762ee337dff48623e729

Cheers! Ahmad Bamieh,

# dante federici (10 months ago)

I'd be -1 on adding something like this to the language. This is better solved with a library.

Transducers are a much better general solution than by stacking or adding special array functions. You don't want to solve the "map with filter" case, since there are many, many more combinations (take after map, filter on map, group with map, etc.).

Some details on transducers: clojure.org/reference/transducers, cognitect-labs/transducers

# Tab Atkins Jr. (10 months ago)

On Fri, Oct 27, 2017 at 8:17 AM, Peter Jaszkowiak <p.jaszkow at gmail.com> wrote:

Actually flatMap isn't even needed. My question is, why use this over a normal map with a conditional? It doesn't seem to really save any space.

Right. The example given:

exampleArray.mapOn(Math.sqrt, Number.isInteger); // [1, 1.414, 3, "A",
"B", "C"];

can be written with today's code as just:

exampleArray.map(x=>Number.isInteger(x) ? Math.sqrt(x) : x);

You're paying only a tiny handful of additional characters for this.


And in any case, specializing this use-case to Array.map only isn't too great. This sort of "conditionally call this function" ability would be useful more generally, with something like:

function onlyIf(cond, func) {
  return (...x)=>cond(...x) ? func(...x) : x;
}
exampleArray.map(onlyIf(Number.isInteger, Math.sqrt));

Feel free to write this into your own code. (Or get super-fancy and put it on Function.prototype, so you can write .map(Math.sqrt.onlyIf(Number.isInteger)) ^_^)

# Ahmad Bamieh (10 months ago)

I found myself using this type of conditionals a lot so i thought it would be a nice addition to the native array arsenal (+1 for getting rid of the if statements), but after reading your comments i believe you are correct. It might be better for such utilities to belong in a small wrapper or part of a utility library like lodash.

Cheers! Ahmad Bamieh,