0% found this document useful (0 votes)
7 views

8A Programming Arrays With Map, Filter and Reduce

Uploaded by

Sophia Lindholm
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

8A Programming Arrays With Map, Filter and Reduce

Uploaded by

Sophia Lindholm
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 51

Programming Arrays with

Map, Filter and Reduce

Cosmin E. Oancea
[email protected]

Department of Computer Science (DIKU)


University of Copenhagen

October 2023
Data Structure

A data structure is:


I a structured way to store data;
I methods to operate on this data (e.g., insert/delete/modify).

So far you have only stored data in variables, which is


limiting (e.g., because you need to know in advance how
many variables you need);

Solution: Arrays;

Last lecture we have programmed arrays with loops,


which can be tedious and perhaps not very intuitive,
but it is very general (i.e., you can accomplish everything.)

This lecture we will try to lift the level of abstraction;


some, hopefully many, will find this way easier.
Today’s Lecture

Key Idea: passing a function as argument to a function

Map: applies a function to each element of an array

Filter: keeps only the elements that succeed under a predicate

Reduce: applies a binary operator to all elemement of an array

Composing Map, Filter and Reduce Vertically and Horizontally

Summary
Passing Functions as Arguments to a Function
Passing functions as arguments to a function is a powerful tool!

f u n c t i o n u n i t Te s t 2 Ar g F u n ( f , a1 , a2 , e x p e c t e d r e s u l t , a r e E q u a l ) {
l e t a c t u a l r e s u l t = f ( a1 , a2 ) ;
i f ( areEqual ( a ct u a l r e s u l t , expected result ) ) {
return ” ” ;
} else {
l e t e r r o r s t r = ” \n\ t E r r o r : a p p l yi n g f u n c t i o n t o arguments : ( ”
+ a1 . t o S t r i n g ( ) + ” , ” + a2 . t o S t r i n g ( ) + ” ) ” +
” re su lt s in ” + a ct u a l r e s u l t +
” instead of ” + expected result ;
return e r r o r s t r ;
}
}

For example, it allows us to write one (generic) validation code for any function that
accepts two parameters:
f: the to-be-tested function;
a1 and a2 are its actual arguments;
expected result: the expected result of the call f(a1,a2)
areEqual: a function that compares whether the expected result equals the actual
result (e.g., because arrays cannot be compared directly with the == operator).
Map, Filter, Reduce
A lot can be accomplished by combining three array methods that
receive functions as arguments/parameters:

map: applies the function argument to each element of an array:


I e.g., multiply each element of an array of numbers by 2.

filter: keeps only the array elements that succeed under a


predicate:
I e.g., keep only the even integers from an array of integers.

reduce: applies a binary function (operator) to all elements of an


array:
I e.g., summing up the elements of an array of numbers.

Think of map and reduce as a way of lifting the behavior of simple


functions (that are defined on the scalars) to operate on entire
arrays instead.
Today’s Lecture

Key Idea: passing a function as argument to a function

Map: applies a function to each element of an array

Filter: keeps only the elements that succeed under a predicate

Reduce: applies a binary operator to all elemement of an array

Composing Map, Filter and Reduce Vertically and Horizontally

Summary
Mapping an Array

function plus1(a) {
return (a+1);
}
let x = [5, 6, 7, 8];
let y = x.map(plus1);
console.log(y); // [6, 7, 8, 9]
console.log(x); // [5, 6, 7, 8]
Mapping an Array

function plus1(a) {
return (a+1);
}
let x = [5, 6, 7, 8];
let y = x.map(plus1);
console.log(y); // [6, 7, 8, 9]
console.log(x); // [5, 6, 7, 8]

What do you think is the semantics of map?


Mapping an Array

function plus1(a) {
return (a+1);
}
let x = [5, 6, 7, 8];
let y = x.map(plus1);
console.log(y); // [6, 7, 8, 9]
console.log(x); // [5, 6, 7, 8]

What do you think is the semantics of map?


map is called on an array, and it receives as argument a
function that takes one argument;
map produces a new array whose elements are obtained by
calling, in order, the function (argument) on each element of
the array it was called on.
Mapping an Array

function plus1(a) {
return (a+1);
}
let x = [5, 6, 7, 8];
let y = x.map(plus1);
console.log(y); // [6, 7, 8, 9]
console.log(x); // [5, 6, 7, 8]

What do you think is the semantics of map?


map is called on an array, and it receives as argument a
function that takes one argument;
map produces a new array whose elements are obtained by
calling, in order, the function (argument) on each element of
the array it was called on.
Essentially, map lifts in a straightforward way a simple function
that operates on scalars to operate on arrays instead.
Syntax for Unnamed (a.k.a., Lambda) Functions

function plus1(a) {
return (a+1);
}
let x = [5, 6, 7, 8];
let y = x.map(plus1); // y = [6, 7, 8, 9]
Syntax for Unnamed (a.k.a., Lambda) Functions

function plus1(a) {
return (a+1);
}
let x = [5, 6, 7, 8];
let y = x.map(plus1); // y = [6, 7, 8, 9]

When the body of the (mapped-)function can be written as one


expression, we can use a more concise syntax that ”inlines” the
function declaration inside the map (reduce or filter), as in:
let y = x.map(a => a+1);

Syntax of Unnamed (Lambda) function:


(var name1 , . . ., var nameq ) => Exp
var name1 , . . ., var nameq are the formal arguments,
Exp is an expression representing the result of the function.
map uses one-argument functions, i.e., (var name1 ) => Exp
Semantics of map
y= [ x0 , x1 , .., xn−1 ].map(f)
↓ ↓ ↓
y≡ [ f(x0 ), f(x1 ), .., f(xn−1 ) ]

What does this do?


["CAT","DOg","MOUSE"].map(x => x.toLowerCase());
Semantics of map
y= [ x0 , x1 , .., xn−1 ].map(f)
↓ ↓ ↓
y≡ [ f(x0 ), f(x1 ), .., f(xn−1 ) ]

What does this do?


["CAT","DOg","MOUSE"].map(x => x.toLowerCase());
//["cat","dog","mouse"]

Consequence: the (array) result of map has the same length as


the array it was called on.
Sanity: the (intended) type of the function argument is the
same as the element type of the array on which map
is called.
What does this do? But is it sane?
["111", 111, "aha", [1,2]].map(x => x + 1);
Semantics of map
y= [ x0 , x1 , .., xn−1 ].map(f)
↓ ↓ ↓
y≡ [ f(x0 ), f(x1 ), .., f(xn−1 ) ]

What does this do?


["CAT","DOg","MOUSE"].map(x => x.toLowerCase());
//["cat","dog","mouse"]

Consequence: the (array) result of map has the same length as


the array it was called on.
Sanity: the (intended) type of the function argument is the
same as the element type of the array on which map
is called.
What does this do? But is it sane?
["111", 111, "aha", [1,2]].map(x => x + 1);
[ "1111", 112, "aha1", "1,21" ]
Demystify Map: A Loop-Based Implementation
let y = arr.map(function (x) { return x+1; });
// adds one to each element of arr
can be written based on loops as:
let y = [];
for(i=0; i<arr.length; i++)
y.push(arr[i]+1);

More general, an implementation of arr.map(f) could be:


Demystify Map: A Loop-Based Implementation
let y = arr.map(function (x) { return x+1; });
// adds one to each element of arr
can be written based on loops as:
let y = [];
for(i=0; i<arr.length; i++)
y.push(arr[i]+1);

More general, an implementation of arr.map(f) could be:


function myMap(arr, f) {
let y = [];
for(i=0; i<arr.length; i++) {
let inp_el = arr[i];
let out_el = f( inp_el );
y.push( out_el );
}
return y;
}
Today’s Lecture

Key Idea: passing a function as argument to a function

Map: applies a function to each element of an array

Filter: keeps only the elements that succeed under a predicate

Reduce: applies a binary operator to all elemement of an array

Composing Map, Filter and Reduce Vertically and Horizontally

Summary
Filtering an Array
function even(a) {
return ( (a%2) == 0 );
}
let x = [5, 6, 7, 8, 9];
let y = x.filter(even); // y = [6, 8]

It can be written more concise as:


let y = x.filter( a => (a%2) == 0);
What do you think is the semantics of filter?
Filtering an Array
function even(a) {
return ( (a%2) == 0 );
}
let x = [5, 6, 7, 8, 9];
let y = x.filter(even); // y = [6, 8]

It can be written more concise as:


let y = x.filter( a => (a%2) == 0);
What do you think is the semantics of filter?
filter is called on an array, and it receives as argument a
predicate, i.e., a function that takes one argument and
returns a boolean (true or false);
filter produces an array by keeping from the array it was
called on, in order, only the elements that succeed (return
true) under the predicate.
Filtering an array
What does this do?
[ ” c a t ” , ” Dog ” , ” mouse ” ] . f i l t e r ( x => x . t o Lo we r Ca s e ( ) = = = x ) ;
Filtering an array
What does this do?
[ ” c a t ” , ” Dog ” , ” mouse ” ] . f i l t e r ( x => x . t o Lo we r Ca s e ( ) = = = x ) ;
//["cat","mouse"]

Consequence: the (array) result of filter has smaller or equal


length than the array it was called on.
Sanity: the (intended) type of the predicate argument is the
same as the element type of the array on which
filter was called.
What does this do? But is it sane?
["5", "6", 7, 8, [2]].filter(x => x%2 === 0);
Filtering an array
What does this do?
[ ” c a t ” , ” Dog ” , ” mouse ” ] . f i l t e r ( x => x . t o Lo we r Ca s e ( ) = = = x ) ;
//["cat","mouse"]

Consequence: the (array) result of filter has smaller or equal


length than the array it was called on.
Sanity: the (intended) type of the predicate argument is the
same as the element type of the array on which
filter was called.
What does this do? But is it sane?
["5", "6", 7, 8, [2]].filter(x => x%2 === 0);
//[ "6", 8, [2] ]

Though this be madness, yet there is method in it (?)


["5", "6", 7, 8, [2,4]].filter(x => x%2 === 0);
Filtering an array
What does this do?
[ ” c a t ” , ” Dog ” , ” mouse ” ] . f i l t e r ( x => x . t o Lo we r Ca s e ( ) = = = x ) ;
//["cat","mouse"]

Consequence: the (array) result of filter has smaller or equal


length than the array it was called on.
Sanity: the (intended) type of the predicate argument is the
same as the element type of the array on which
filter was called.
What does this do? But is it sane?
["5", "6", 7, 8, [2]].filter(x => x%2 === 0);
//[ "6", 8, [2] ]

Though this be madness, yet there is method in it (?)


["5", "6", 7, 8, [2,4]].filter(x => x%2 === 0);
//[ "6", 8 ]
Demystifying Filter: A Loop-Based Implementation
let y= arr.filter(function (a) { return (a%2==0); })
// keeps only the even numbers from arr
can be written based on loops as:
let y = [];
for(i=0; i<arr.length; i++) {
// think 2 min in pairs how to implement this
}
More general, an implementation of arr.filter(p) could be:
function myFilter(arr, p) {
let y = [];
for(i=0; i<arr.length; i++) {
// what should we write here ???
}
return y;
}
Demystifying Filter: A Loop-Based Implementation
let y= arr.filter(function (a) { return (a%2==0); })
// keeps only the even numbers from arr
can be written based on loops as:
let y = [];
for(i=0; i<arr.length; i++) {
let el = arr[i];
if (el % 2 == 0) { y.push(el); }
}
More general, an implementation of arr.filter(p) could be:
function myFilter(arr, p) {
let y = [];
for(i=0; i<arr.length; i++) {
let el = arr[i];
if ( p(el) ) { y.push(el); }
}
return y;
Today’s Lecture

Key Idea: passing a function as argument to a function

Map: applies a function to each element of an array

Filter: keeps only the elements that succeed under a predicate

Reduce: applies a binary operator to all elemement of an array

Composing Map, Filter and Reduce Vertically and Horizontally

Summary
Reducing an Array
function plus(acc, elem) {
return (acc + elem);
}
let x = [5, 6, 7, 8];
let y = x.reduce(plus, 0);
// y = (((0 + 5) + 6) + 7) + 8 = 26
Reducing an Array
function plus(acc, elem) {
return (acc + elem);
}
let x = [5, 6, 7, 8];
let y = x.reduce(plus, 0);
// y = (((0 + 5) + 6) + 7) + 8 = 26
It can be written more concise as:
let y = x.reduce( (x,y) => x+y, 0 );
What should this compute?
function mul(acc, elem) {
// first arg (acc) is the accumulator
// second arg (elem) is an array element
return (acc * elem);
}
[5, 2, 8, 10].reduce(mul, 2);
Reducing an Array
function plus(acc, elem) {
return (acc + elem);
}
let x = [5, 6, 7, 8];
let y = x.reduce(plus, 0);
// y = (((0 + 5) + 6) + 7) + 8 = 26
It can be written more concise as:
let y = x.reduce( (x,y) => x+y, 0 );
What should this compute?
function mul(acc, elem) {
// first arg (acc) is the accumulator
// second arg (elem) is an array element
return (acc * elem);
}
[5, 2, 8, 10].reduce(mul, 2);
//(((2 * 5) * 2) * 8) * 10 = 1600
Semantics of Reduce: Important Intuition
Reduce lifts the behavior of a binary function that operates on
two arguments to operate instead on an arbitrary number of
arguments, i.e., on all elements of an array, for example:

+ adds two integers → reduce with + sums up all elements


of an array;

* multiplies two integers → reduce with * computes the


product of all elements of an array;

one can write a small function that selects the smallest of its
two arguments → reduce with this function selects the
minimal element of an array.

Cosmin is perfectly happy if you can remember this intuition;


for completeness, the next slide presents the precise semantics.
Semantics of reduce
Only for intuition, with binary-operator notation (illegal syntax):
y = [x0 , x1 , ..., xn−1 ].reduce( , a)
y ≡ (. . . (((a x0 ) x1 ) x2 ) . . . xn−1 )

Or with function notation (legal syntax):


y = [x0 , x1 , ..., xn−1 ].reduce(f, a)
y ≡ f(...f(f(f(a, x0 ), x1 ), x2 )..., xn−1 )

reduce receives as argument a binary operator f (function


with two arguments) and an initial value (a);
If the array it is called on is empty, the result of reduce is the
initial value, e.g., [].reduce(plus, 4) results in 4.
Otherwise
I In the first step, reduce applies the function to the initial
value and the first element of the array;
I In the other steps, reduce successively applies the function
to the value computed in the previous step and the next
element of the array, until all elements are processed.
Reducing an Array: Sanity Conditions
What does this do?
arr = ["like ","reduce ","a ","lot!"];
arr.reduce((x,y) => x+y, "I ");
Reducing an Array: Sanity Conditions
What does this do?
arr = ["like ","reduce ","a ","lot!"];
arr.reduce((x,y) => x+y, "I ");
//"I like reduce a lot!"

What does this do?


arr.reduce((x,y) => x+y.length, 1);
Reducing an Array: Sanity Conditions
What does this do?
arr = ["like ","reduce ","a ","lot!"];
arr.reduce((x,y) => x+y, "I ");
//"I like reduce a lot!"

What does this do?


arr.reduce((x,y) => x+y.length, 1);
// (((1+5)+7)+2)+4 = 19

Observation: the arguments of the function do not have to be of


the same type!
Reducing an Array: Sanity Conditions
What does this do?
arr = ["like ","reduce ","a ","lot!"];
arr.reduce((x,y) => x+y, "I ");
//"I like reduce a lot!"

What does this do?


arr.reduce((x,y) => x+y.length, 1);
// (((1+5)+7)+2)+4 = 19

Observation: the arguments of the function do not have to be of


the same type! (x is a number, y is a string!)
Sanity 1: the elements of the array have the same type;
Sanity 2: the 1st argument and the result of the binary operator
(function) has the same type as the initial value;
Sanity 3: the 2nd argument of the binary operator (function) has the
same type as the array elements (since it iterates over them);
Demystifying Reduce: A Loop-Based Implementation
let y= arr.reduce((acc,el) => acc+el, 0);
// sums up the elements of arr
can be written based on loops as:
let y = ???;
for(i=0; i<arr.length; i++) {
y = ???;
}
An implementation of arr.reduce(binop, ne) could be:
function myReduce(arr, binop, ne) {
let y = ???;
for(i=0; i<arr.length; i++) {
y = ???;
}
return y;
}
Demystifying Reduce: A Loop-Based Implementation
let y= arr.reduce((acc,el) => acc+el, 0);
// sums up the elements of arr
can be written based on loops as:
let y = 0;
for(i=0; i<arr.length; i++) {
y = y + arr[i];
}
An implementation of arr.reduce(binop, ne) could be:
function myReduce(arr, binop, ne) {
let y = ne;
for(i=0; i<arr.length; i++) {
y = binop(y, arr[i]);
}
return y;
}
Today’s Lecture

Key Idea: passing a function as argument to a function

Map: applies a function to each element of an array

Filter: keeps only the elements that succeed under a predicate

Reduce: applies a binary operator to all elemement of an array

Composing Map, Filter and Reduce Vertically and Horizontally

Summary
Vertical Nesting: Doubling Each Element of a Matrix
Problem: from an input matrix (table of numbers), we want to create a new matrix that has
the same shape as the input matrix and whose elements are obtained by multiplying by
two the elements of the corresponding elements of the input matrix.

Show example on whiteboard!

Implementation plan:
Vertical Nesting: Doubling Each Element of a Matrix
Problem: from an input matrix (table of numbers), we want to create a new matrix that has
the same shape as the input matrix and whose elements are obtained by multiplying by
two the elements of the corresponding elements of the input matrix.

Show example on whiteboard!

Implementation plan:
(1) write a function that multiplies by two its (only) argument;
(2) write a function that multiplies by two each element of a vector,
by mapping the input vector with the function of step (1);
(3) write the function that solves our problem by mapping the input matrix with the
function of step (2).
(4) implement the target function directly in one line by using nested maps with
lambda functions.
Vertical Nesting: Doubling Each Element of a Matrix
Problem: from an input matrix (table of numbers), we want to create a new matrix that has
the same shape as the input matrix and whose elements are obtained by multiplying by
two the elements of the corresponding elements of the input matrix.

Show example on whiteboard!

Implementation plan:
(1) write a function that multiplies by two its (only) argument;
(2) write a function that multiplies by two each element of a vector,
by mapping the input vector with the function of step (1);
(3) write the function that solves our problem by mapping the input matrix with the
function of step (2).
(4) implement the target function directly in one line by using nested maps with
lambda functions.

f u n c t i o n m u l 2 S ca l a r ( a ) { r e t u r n 2 * a ; }

f u n c t i o n m u l 2 Ve ct o r ( v c t ) { r e t u r n v c t . map ( m u l 2 S ca l a r ) ; }

f u n c t i o n mu l2 Mat rix ( mat ) { r e t u r n mat . map ( m u l 2 Ve ct o r ) ; }

f u n c t i o n m u l 2 M a t r i xN e s t ( mat ) {
r e t u r n mat . map ( row => row . map ( a => 2 * a ) ) ;
}
Filter Out the Odd Numbers of Each Row of A Matrix
Problem: we want to create a new matrix by filtering out all the odd elements (i.e., keep
the even ones) from each row of an input matrix.

Show example on whiteboard!

Implementation plan:
Filter Out the Odd Numbers of Each Row of A Matrix
Problem: we want to create a new matrix by filtering out all the odd elements (i.e., keep
the even ones) from each row of an input matrix.

Show example on whiteboard!

Implementation plan:
(1) write a function that returns true if the argument is an even number and false
otherwise;
(2) write a function that keeps only the even elements of a vector,
by applying filter with the operator defined at step (1);
(3) write a function that solves our problem by mapping the input matrix with the
function of step (2).
(4) implement the target function directly in one line by using a filter nested inside a
map, both being written with lambda functions.
Filter Out the Odd Numbers of Each Row of A Matrix
Problem: we want to create a new matrix by filtering out all the odd elements (i.e., keep
the even ones) from each row of an input matrix.

Show example on whiteboard!

Implementation plan:
(1) write a function that returns true if the argument is an even number and false
otherwise;
(2) write a function that keeps only the even elements of a vector,
by applying filter with the operator defined at step (1);
(3) write a function that solves our problem by mapping the input matrix with the
function of step (2).
(4) implement the target function directly in one line by using a filter nested inside a
map, both being written with lambda functions.

f u n c t i o n i s E ve n ( a ) { r e t u r n ( ( a % 2 ) == 0 ) ; }

f u n c t i o n f i l t e r V e c t o r ( v c t ) { r e t u r n v c t . f i l t e r ( i s E ve n ) ; }

f u n c t i o n m a p F i l t e r ( mat ) { r e t u r n mat . map ( f i l t e r V e c t o r ); }

f u n c t i o n m a p F i l t e r N e s t ( mat ) {
r e t u r n mat . map ( row => row . f i l t e r ( a => ( a % 2 ) == 0 ) ) ;
}
Find the Maximal Element of Each Row of A Matrix
Problem: we want to create a new vector by selecting the maximal element of each row of
an input matrix (table of numbers).

Show example on whiteboard!

Implementation plan:
Find the Maximal Element of Each Row of A Matrix
Problem: we want to create a new vector by selecting the maximal element of each row of
an input matrix (table of numbers).

Show example on whiteboard!

Implementation plan:
(1) write a function that returns the larger of its two arguments;
(2) write a function that selects the maximal element of a vector,
by applying reduce with the operator defined at step (1) and what initial
accumulator?
(3) write a function that solves our problem by mapping the input matrix with the
function of step (2).
(4) implement the target function directly in one line by using a reduce nested inside a
map, both being written with lambda functions.
Find the Maximal Element of Each Row of A Matrix
Problem: we want to create a new vector by selecting the maximal element of each row of
an input matrix (table of numbers).

Show example on whiteboard!

Implementation plan:
(1) write a function that returns the larger of its two arguments;
(2) write a function that selects the maximal element of a vector,
by applying reduce with the operator defined at step (1) and what initial
accumulator?
(3) write a function that solves our problem by mapping the input matrix with the
function of step (2).
(4) implement the target function directly in one line by using a reduce nested inside a
map, both being written with lambda functions.

f u n c t i o n max ( a , b ) { i f a > b then r e t u r n a ; e l s e r e t u r n b ; }

f u n c t i o n maxVectorElm ( v c t ) { r e t u r n v c t . r e d u ce ( max , − I n f i n i t y ) ; }

f u n c t i o n mapReduce ( mat ) { r e t u r n mat . map ( maxVectorElm ) ; }

f u n c t i o n mapReduceNest ( mat ) {
r e t u r n mat . map ( row => row . r e d u ce ( ( a , b ) => max ( a , b ) , − I n f i n i t y ) ) ;
}
Horizontal Nesting: String Processing Example
Problem: we want to process a string inp str that consists of words separated by
comma and/or spaces in the following way:
(1) replace the commas with empty spaces: this can be achieved with
let step1 str = inp str.replace(/[,]/g, " ")
(2) split the string into an array of words using space (” ”) as separator:
this can be achieved with step1 str.split(" ")
(3) removing the words that are empty strings or that represent numbers from the array
obtained at step (2)
(4) upper-casing all words of the array obtained at step (3) and adding an ”—” character
at the end of each.
(5) concatenating back all words into a string.

"99,Yummy cookies,then,, 5 exercises,then 2 movies,, is 77 fine"


⇒ "Yummy|cookies|then|exercises|then|movies|is|fine|"

function processString ( i n p s t r ) {
l e t s t e p 1 s t r = i n p s t r . replace ( / [ , ] / g , ” ” ) ; / / r e p l a ce s ’ , ’ with ’ ’
l e t s t e p 2 a r r = s t e p 1 s t r . s p l i t ( ” ” ) ; / / p r o d u c e s an a r r a y o f wo r d s
l e t step3 arr = step2 arr . ???
l e t step4 arr = step3 arr . ???
let res str = step4 arr . ???
return r e s s t r ;
}
Horizontal Nesting: String Processing Example
Problem: we want to process a string inp str that consists of words separated by
comma and/or spaces in the following way:
(1) replace the commas with empty spaces: this can be achieved with let
step1 str = inp str.replace(/[,]/g, " ")
(2) split the string into an array of words using space (” ”) as separator: this can be
achieved with step1 str.split(" ")
(3) removing the words that are empty strings or that represent numbers from the array
obtained at step (2)
(4) upper-casing all words of the array obtained at step (3) and adding an ”—” character
at the end of each.
(5) concatenating back all words into a string that starts with ”—”.

"99,Yummy cookies,then,, 5 exercises,then 2 movies,, is 77 fine"


⇒ "|YUMMY|COOKIES|THEN|EXERCISES|THEN|MOVIES|IS|FINE|"

function processString ( i n p s t r ) {
l e t s t e p 1 s t r = i n p s t r . replace ( / [ , ] / g , ” ” ) ;
let step2 arr = step1 str . split ( ” ” ) ;
l e t s t e p 3 a r r = s t e p 2 a r r . f i l t e r ( a => a ! = = ” ” && isNaN ( a ) )
l e t s t e p 4 a r r = s t e p 3 a r r . map ( word => word . toUpperCase ( ) + ” | ” )
let res str = s t e p 4 a r r . r e d u ce ( ( a , b ) −> a +b , ” | ” )
return r e s s t r ;
}
Can also be written in one very-long line (on whiteboard, please).
Summary

Map, reduce and filter lift the behavior of simple functions


that operate on scalars to ones that operate on arrays
instead.

You can reach far with map-filter-reduce, but you


cannot do everything with them – loops are still necessary!

There are lots of goodies in the standard library: map, reduce,


filter, but also replace, split, etc.

Remember the syntax for calling the methods of arrays:


name-of-the-array-variable.method-name( argExpressions )
where method-name can be push or map or . . ., and
argExpressions are the element to be pushed or the function
to be mapped, or . . .

You might also like