JavaScript map & find at the same time: findMap?
Built-in map
is greedy so you have to write your own, lazy version:
const a = [2, 5, 78, 4];
const expensiveFunction = n => {
console.log('expensiveFunction for', n);
return 2 * n
};
function *map(a, fn) {
for(let x of a)
yield fn(x);
}
function find(a, fn) {
for(let x of a)
if (fn(x))
return x;
}
r = find(map(a, expensiveFunction), x => x > 100)
console.log('result', r)
Unlike the stock map
, this map
is a generator and returns (yields) results on demand rather than processing the whole array at once. find
and map
in this example are "coroutines" and play some kind of a ping-pong game where find
asks for results and map
delivers them when asked. As soon as find
is satisfied with what it's got, it quits and so does map
, because nobody is asking for its results anymore.
You can also add map
, find
and friends to the IteratorPrototype
to make them available for all iterators and be able to use dot notation:
const IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
Object.defineProperties(IteratorPrototype, {
map: {
value: function* (fn) {
for (let x of this) {
yield fn(x);
}
},
enumerable: false
},
find: {
value: function (fn) {
for (let x of this) {
if (fn(x))
return x;
}
},
enumerable: false
},
});
//
const a = [2, 5, 78, 4];
const expensiveFunction = n => {
console.log('expensiveFunction', n);
return 2 * n
};
let r = a.values().map(expensiveFunction).find(x => x > 100);
console.log(r)
Here's a small library based on this technique: https://github.com/gebrkn/armita
Something like this
const a = [2, 5, 78, 4];
const expensiveFunction = n => 2 * n;
let findMap = arr => {
let found = arr.find(a => expensiveFunction(a) > 100)
return found !== undefined ? expensiveFunction(found) : found
}
console.log(findMap(a));
Alert:- JUST out of curiosity , But hacky or you can call it misuse of find
const a = [2, 5, 78, 4];
const expensiveFunction = n => 2 * n;
let findMap = arr => {
let returnValue;
let found = arr.find(a => {
returnValue = expensiveFunction(a)
return returnValue > 100
})
return returnValue
}
console.log(findMap(a));