I would like to propose a new Array.prototype function that does a filter and map in a single iteration ("filMap"), I'm aware of .reduce function, however this would allow the user work in a more direct way with the familiarity of both .map and .filter functions
// Typescript
Array.prototype.filMap = function <T, K>(
filterFn: (item: T, index: number, array: T[]) => boolean | undefined,
mapperFn: (item: T, index: number, array: T[]) => K,
thisArg?: any
) {
const result: K[] = [];
for (let i = 0; i < this.length; i++) {
if (filterFn.call(thisArg, this[i], i, this)) {
result.push(mapperFn.call(thisArg, this[i], i, this));
}
}
return result;
};
// Polyfill
Array.prototype.filMap = function (filterFn, mapperFn) {
if (this == null)
throw TypeError("this is null or undefined");
if (typeof filterFn !== "function")
throw TypeError("filter callback is not a function");
if (typeof mapperFn !== "function")
throw TypeError("mapper callback is not a function");
const O = Object(this);
const len = O.length >>> 0;
let T;
if (arguments.length > 2) {
T = arguments[2];
}
const A = new Array(len);
let k = 0;
let to = 0;
while (k < len) {
if (k in O) {
const kValue = O[k];
if (filterFn.call(T, kValue, k, O)) {
const kResult = mapperFn.call(T, kValue, k, O);
A[to] = kResult;
to += 1;
}
}
k += 1;
}
A.length = to;
return A;
};
// Typings
declare global {
interface Array<T> {
/**
* Calls a filter function on each element of the array and
* then run a mapper function for elements that passed the criteria
*
* @param filterFn A Function that returns true for qualifying elements,
* receives 3 elements as arguments
* (current element, index of current element and the array being iterated)
* @param mapperFn A function that returns the desired mapped element,
* this will run only for elements that passed filter criteria
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value
*/
filMap<K>(
filterFn: (element: T, index: number, array: T[]) => boolean | undefined,
mapperFn: (element: T, index: number, array: T[]) => K,
thisArg?: any
): K[];
}
}
Examples:
const numbers = [1,2,3,4,5,6];
// Get odds numbers multiplied by 3
// with .filMap
numbers.filMap((n) => n % 2 !== 0, (n) => n * 3);
// with .map and .filter
numbers.filter((n) => n % 2 !== 0).map((n) => n * 3);
// with reduce
numbers.reduce((p, c) => {
if (c % 2 !== 0) p.push(c * 3);
return p;
}, []);