function each(coll, f) {
if (Array.isArray(coll)) {
for (var i = 0; i < coll.length; i++) {
f(coll[i], i);
}
} else {
for (var key in coll) {
f(coll[key], key);
}
}
}
function filter(array, predicate) {
var acc = [];
each(array, function(element, i) {
if (predicate(element, i)) {
acc.push(element);
}
});
return acc;
}Use filter to write the following functions:
-
Write a function called
evensthat takes an array of numbers as a parameter, and returns an array of only the even numbers in the parameter. -
Write a function called
multiplesOfThreethat takes an array of numbers as a parameter, and returns an array of only the numbers that are multiples of three. -
Write a function called
positivesthat takes an array of numbers as a parameter, and returns an array of only the numbers that are positive. -
Write a function called
evenLengththat takes an array of strings and returns an array of only the strings with an even length.
-
Use
filterto write the following functions:odds: Accepts an array of numbers, and returns the odd ones.negatives: Likepositives, but with negatives!largerThanSix: given an array of numbers, returns those larger than 6.
-
Using
filter, write a functionstartsWithCharthat accepts two parameters: an array of strings, and a character (e.g. "a"), and returns an array of only the strings that start with that character:function startsWithChar(strings, character) { // ... } var words = "the quick brown fox jumps over the lazy dog".split(" "); startsWithChar(words, "q"); // => ["quick"] startsWithChar(words, "t"); // => ["the", "the"]
-
Extend the
filterfunction to pass the index of each element to the predicate; then, complete the following:Write a function called
evenIndexedEvenLengths(yeah, a bit of a mouthful) that accepts an array of strings as a parameter, and returns only the strings that are found at an even index that also have an even length, e.g.:function evenIndexedEvenLengths(strings) { // TODO: your code here } evenIndexedEvenLengths(["lion", "monkey", "aardvaark", "cat", "doge"]); // => ["lion", "doge"] evenIndexedEvenLengths(["red", "green", "purple", "blue", "yellow"]); // => ["purple", "yellow"]
HINT: You'll need to ensure that your version of
filteralso passes each elements' index (or key in the case of objects) to the predicate. -
Write a version of
filterthat works on arrays and objects; then, use your updated version offilterto filter an object with values of mixed types to an object with only numeric values. You should be able to use your modified version offilteras follows:filter({a: 1, b: "dog", c: true}, function(value) { return typeof value === "number"; }); // => {a: 1}
function reduce(array, f, start) {
var acc = start;
each(array, function(element) {
acc = f(acc, element);
});
return acc;
}-
We've shown that we can write the function
sum-- which sums an array of numbers -- usingreducelike this (see slides for more):function sum(numbers) { return reduce(numbers, function(total, number) { return total + number; }, 0); }
Replace the
???below to complete the implementation ofproduct, that returns the product of an array of numbers.function product(numbers) { return reduce(???, function(???, number) { return ??? * number; }, ???); }
-
Rewrite the
averageAgefunction from the warmup usingreduce. The function signature and people array are copied below for your convenience:var people = [ {name: {first: "Alyssa", middle: "P.", last: "Hacker"}, age: 26}, {name: {first: "Ben", last: "Bitdiddle"}, age: 34}, {name: {first: "Eva", middle: "Lu", last: "Ator"}, age: 40}, {name: {first: "Lem", middle: "E.", last: "Tweakit"}, age: 45}, {name: {first: "Louis", last: "Reasoner"}, age: 21} ]; function averageAge(people) { // First you'll need to compute the sum of all the ages // Second, divide the sum by the number of people (people.length) // YOUR CODE HERE }
-
The
rangefunction from yesterday looks like this:function range(start, end) { var acc = []; for (var i = start; i < end; i++) { acc.push(i); } return acc; }
Using
rangeandreduce, complete the factorial function below that should compute the factorial ofn.function factorial(n) { // YOUR CODE HERE }
HINT: If you cannot think of how to do this, it may help to first try writing the function using
each, and then refactor it to userange&reduce.
-
The
sumByfunction from previous lessons can be implemented usingeachlike this:function sumBy(numbers, f) { var sum = 0; each(numbers, function(number) { sum = sum + f(number); }); return sum; }
Rewrite
sumByusingreduce. -
The
maxfunction below takes an array of numbers as a parameter, and returns the maximum number in the array:function max(numbers) { var max = numbers[0]; each(numbers, function(number) { if (number > max) { max = number; } }); return max; }
Rewrite
maxusingreduce. -
Write a function called
countOccurrencesthat, given a string and a character (a string with length one) as parameters, returns the total number of times that character occurs in the string. For example:countOccurrences("hello", "l"); // => 2 countOccurrences("the", "z"); // => 0 countOccurrences("hello, world!", "l"); // => 3
-
In the lecture (see slides) we ran through a function called
everyNumberEven-- write functions like it that do the following:- Given an array of numbers, determine if every one of them is odd
- Given an array of numbers, determine if every one of them is positive
- Given an array of strings, determine if all of them have a length greather than 3.
- Given an array of strings, determines if all of them contain the letter "e".
-
Write a function
everythat takes two parameters: an array and a predicate (a function that returns true or false).everyshould returntrueif the predicate returnstruefor every element in the array. You should be able to use it to writeeveryNumberEvenlike this:function everyNumberEven(numbers) { return every(numbers, function(number) { return number % 2 === 0; }); }
Test that it works by rewriting the functions in exercise (4) above using
every.
-
Let's write a function called
jointhat works just like the built-injoin, but usingreduce! If you're unfamiliar with the built-in version of join, this is how it works:["the", "quick", "brown", "fox"].join(" "); // => "the quick brown fox" ["one", "two", "three"].join(":"); // => "one:two:three"
Part One: First, write a function called
joinWiththat takes three arguments: the string to join onto, the string that will be joined, and a separator. That is, it should work like this:function joinWith(onto, next, separator) { // YOUR CODE HERE } joinWith("the quick", "brown", " "); // => "the quick brown" joinWith("one:two", "three", ":"); // => "one:two:three"
Part Two: Now, using
joinWithandreduce, writejoin:function join(array, separator) { // YOUR CODE HERE } join(["the", "quick", "brown", "fox"], " "); // => "the quick brown fox" join(["one", "two", "three"], ":"); // => "one:two:three"
-
Uses of
reduceare not restricted to turning arrays into numbers -- usereduceto rewritemap(instead of usingeach). -
We previously covered the function
countWordsthat worked like this:function countWords(s) { var acc = {}; var words = s.split(" "); for (var i = 0; i < words.length; i = i + 1) { var word = words[i]; if (acc[word] === undefined) { acc[word] = 1; } else { acc[word]++; } } return acc; }
-
Rewrite
countWordsusingreduce. -
Write the function
countCharsthat works likecountWords, but counts characters instead of words (usingreduceof course).
-
function each(coll, f) {
if (Array.isArray(coll)) {
for (var i = 0; i < coll.length; i++) {
f(coll[i], i);
}
} else {
for (var key in coll) {
f(coll[key], key);
}
}
}
function reduce(array, f, acc) {
if (acc === undefined) {
acc = array[0];
array = array.slice(1);
}
each(array, function(element, i) {
acc = f(acc, element, i);
});
return acc;
}-
The
factorialfunction can be written usingreduceandrange; and furthermore, this is a case where the initial value can be omitted. Writefactorialusing our updated version ofreduceand omit the third argument.HINT: Remember that the
factorialof a numbernis the product of all of the numbers from1ton, and therangefunction (shown below in problem 3) produces an array of numbers fromstarttoend... -
Use the updated version of
reduceto write a functionmaxthat computes the maximum number in an array of numbers. Be sure to not include the third argument (the starting point). -
The
rangefunction that we've explored so far looks like this:function range(start, end) { var acc = []; for (var i = start; i < end; i++) { acc.push(i); } return acc; }
Modify
rangeso that theendparameter is optional, and in the event that it is not supplied,rangecomputes a range from0tostart.
There is a way to implement reduce such that it works on both arrays and
objects. You'll likely want to make use of Object.keys function.