Quick Index
Overview


In this lab we will experiment with three instance methods available on JavaScript Array objects.

As beginners, we'll be more interested in "map" and "filter", but we'll touch on "reduce" also.

map


Array has a method "map" that generates a new array by mapping each element into a new element using a mapping function we provide.

The passed function "maps" an input object into an output object. All elements are mapped, resulting in a new array with the "mapped" elements.

Examples will show this best.

Three examples are shown (squares, cubes, and +1).

Note that we are embedding the function directly into the message send here. In other examples we will show how to assign functions to variables.

let a1, a2, a3, a4;

a1 = [1, 2, 3, 4];

a2 = a1.map(x => x*x);
//[1, 4, 9, 16]

a3 = a1.map(x => x*x*x);
//[1, 8, 27, 64]

a4 = a1.map(x => x + 1);
//[2, 3, 4, 5]
This time we operate on an array of names (strings).

For "a2", we add the prefix "Ms. " to each string.

For "a3", we convert the name to all lowercase.

For "a4", we get the name lengths

let a1, a2, a3, a4;

a1 = ['Riya', 'Asha', 'Anna'];

a2 = a1.map(name => 'Ms. ' + name);
//['Ms. Riya', 'Ms. Asha', 'Ms. Anna']

a3 = a1.map(name => name.toLowerCase());
//['riya', 'asha', 'anna']

a4 = a1.map(name => name.length)
//[4, 4, 4]
The map function supports a second (optional) param
which is the iteration index. Let's take a look.

let a1, a2, a3, a4;

a1 = ['Riya', 'Asha', 'Anna'];

a2 = a1.map((name, index) => `Ms. ${name} (${index})`);
//[ 'Ms. Riya (0)', 'Ms. Asha (1)', 'Ms. Anna (2)' ]

filter


Array has a method "filter" that generates a new array that includes only the elements that pass a match function that we provide.

Examples will show this best.

Three examples are shown:

  • a2 = select nums greater than 20
  • a3 = select nums between 15 and 35
  • a4 = select nums equal to 8 (which results in an empty set)

let a1, a2, a3, a4;

a1 = [40, 10, 30, 20];

a2 = a1.filter(x => x > 20)
//[40, 30]

a3 = a1.filter(x => x >= 15 && x <= 35)
//[30, 20]

a4 = a1.filter(x => x === 8)
//[]
This time we apply a filter to an array of names (strings).

For "a2", we filter to names that begin with 'A'.

For "a3", we filter to names that do NOT begin with 'A'.

let a1, a2, a3, a4;

a1 = ['Riya', 'Asha', 'Anna'];

a2 = a1.filter(name => name.startsWith('A'))
//['Asha', 'Anna']

a3 = a1.filter(name => !name.startsWith('A'))
//['Riya']

reduce


Array has a method "reduce" that behaves differently than "map" and "filter". This method "reduces" the array to one value (e.g. a sum) and returns the one reduced value.

Examples will show this best.

In "reduce(fct, 0)" the 0 is the initial value for our funtions "runningSum" var (also called the "accumulator").

Iteration Play-by-Play:

runningSumeach
040
0+40=4020
40+20=6030
60+30=9010

The final sum is 90 + 10 = 100

let array, fct, sum;

array = [40, 20, 30, 10];

fct = (runningSum, each) => runningSum + each;
sum = array.reduce(fct, 0);

prn(sum);
//100
If you are the type who likes to understand the roots, here is how you can setup an experiment (using the previous example) that will print out values during each loop.

The output is:
 runningSum: 0
each: 40
runningSum: 40
each: 20
runningSum: 60
each: 30
runningSum: 90
each: 10
100


let array, fct, sum;

array = [40, 20, 30, 10];

fct = (runningSum, each) => {
	prn("runningSum: " + runningSum);
	prn("each: " + each);
	return runningSum + each;
}
sum = array.reduce(fct, 0);

prn(sum);
//100
This time we apply the reduce function on an array of names (strings).

Note on our message send "reduce(shorterFct)", that we do not send the second param, which means reduce will use the first array element as the initial value, and start iteration with the second element.

let names, shorterFct, shortest;

names = ['Asha', 'Jemima', 'Anna', 'Vy'];

shorterFct = (nm1, nm2) => (nm1.length < nm2.length) ? nm1 : nm2;
shortest = names.reduce(shorterFct);

prn(shortest);
//Vy

prn(shortest.length);
//2
Reducing is flexible. Anything we can reduce from many to one.

Think about a collection of associations (key-values). We could easily reduce (morph) these into a map as shown below.
A practical example is URLSearchParams (key-values).

let keyValues, fct, map;

keyValues = [['firstName', 'Asha'], ['lastName', 'Kingston']];

//fct takes a map as the "accumulator"
//and adds a new entry for each array element
fct = (aMap, eachPair) => {aMap[eachPair[0]] = eachPair[1]; return aMap;}

//reduce it (starting with empty map as accumulator)
map =  keyValues.reduce(fct, {});

//two ways to use map
const
	fn = map.firstName,
	ln = map['lastName'];

prn(`Full Name: ${fn} ${ln}`);
//Full Name: Asha -- Kingston


separate by newlines
bodyOnly=true
reduceConcatenate() {
	let a = [10, 20, 30, 40];
	prn(a);
	prn(a.reduce((s, ea) => s + ea + '\n', ''));
	//output is four lines, one for each element
}

More Example Sources


Here are a couple (among many more) online related example sources: