Iterators
Iterators are built-in Array functions. They iterate through an array and use a callback to do something to, or with, the the values in that array.
Couldn't we just use for
-loops? Totall! But writing for
loops is error prone and tiring, which is why Javascript provides these iterators to perform common operations for us.
run some piece of logic on each item
create a new array with each item being slightly transformed
filter the array to contain only a subset of items
combine all the items in some fashion
The iterators for these operations are, respectively:
General Practice
Declare an array
Call an iterator on the array
Pass a function to the iterator
Get results
forEach
What
forEach
is the basic replacement for your standard for
loop.
How
Take the body from your for
loop, wrap it in a function, and pass that as the callback argument to forEach
. This iterator will take each array value and one-by-one pass these values into your callback function.
Examples:
const friends = ["Markus", "Tim", "Ilias", "Elie"];
// old way, with a for loop
for (let i = 0; i < friends.length; i++) {
console.log("Hello, " + friends[i] + "!");
}
// cool new way, with the .forEach iterator
friends.forEach((buddy)=>{
console.log("Hello, " + buddy + "!");
});
// both output the same thing
// > Hello, Markus!
// > Hello, Tim!
// > Hello, Ilias!
// > Hello, Elie!
Try it
Use the .forEach
iterator to loop over the following array of foods and say you like them.
const foods = ["pizza", "tacos", "ice cream"];
// your code here
// The output should be
// > "I like pizza"
// > "I like tacos"
// > "I like ice cream"
Try it again
Use the .forEach
iterator to loop over the following array of objects and say how delicious each one is.
const foods = [
{name: "Pizza", level: "very"},
{name: "Tacos", level: "mostly"},
{name: "Cottage Cheese", level: "not very"}
];
// your code here
// The output should be
// > Pizza is very delicious
// > Tacos is mostly delicious
// > Cottage Cheese is not very delicious
map
What:
Use the values from an array to build a new array. In other words: Map the values from one array into another new array and return that new array.
How:
Like forEach
, map will one-by-one pass the values from the array into your callback function. You must return a value in your callback function, and this will be the value that appears in the new array.
Examples:
Create a new array where all the values from the old array are capitalized.
const names = ["tim thompson", "ilias iliad", "elie ellison", "markus mourning"];
// old way with for loop
const cased = [];
for (let i = 0; i < names.length; i++) {
cased.push(names[i].toUpperCase());
}
console.log(cased);
// new way with `map`
const cased = names.map((person) => {
return person.toUpperCase();
});
console.log(cased);
// Should output
// > ['TIM THOMPSON', 'ILIAS ILIAD', 'ELIE ELLISON', 'MARKUS MOURNING']
// > ['TIM THOMPSON', 'ILIAS ILIAD', 'ELIE ELLISON', 'MARKUS MOURNING']
Use map
to create an array of objects with a firstName
property and a lastName
property
const names = ["tim thompson", "ilias iliad", "elie ellison", "markus mourning"];
const splitName = (fullName) => {
return {
firstName: fullName.split(" ")[0],
lastName: fullName.split(" ")[1]
}
}
const objNames = names.map(splitName);
console.log(objNames);
// Should output
// > [ { firstName: 'tim', lastName: 'thompson' },
{ firstName: 'ilias', lastName: 'iliad' },
{ firstName: 'elie', lastName: 'ellison' },
{ firstName: 'markus', lastName: 'mourning' } ]
Challenge: Modify splitName
to account for the possibility of a middle name that will store as a middleName
property.
const names = ["tim toby thompson", "ilias iliad", "elie ellison", "markus mary mourning"];
const splitName = (fullName) => {
const nameArr = fullName.split(" ")
const nameObj = {firstName: nameArr[0]};
if(nameArr.length===3) {
nameObj.middleName = nameArr[1];
nameObj.lastName = nameArr[2];
} else {
nameObj.lastName= nameArr[1];
}
return nameObj;
}
const objNames = names.map(splitName);
// Should output
// > [ { firstName: 'tim', middleName: 'toby', lastName: 'thompson' },
{ firstName: 'ilias', lastName: 'iliad' },
{ firstName: 'elie', lastName: 'ellison' },
{ firstName: 'markus', middleName: 'mary', lastName: 'mourning' } ]
Use map
to create a new array strNums
that holds the same values as intNums
but as strings instead of integers
const intNums = [0, 1, 2, 3, 4, 5]
const strNums = intNums.map((elem) => {
return elem.toString();
});
console.log(strNums);
filter
What:
Returns a subset of the original array by iterating through the original array and filtering out values.
How:
Your callback must return a boolean. filter
will one-by-one pass the values from the array into your callback. If the callback returns true
, that element is included in the returned new array, otherwise it is excluded.
Examples:
Use filter
to get 2 new arrays - one that contains names of even length only and one that contains names of odd length only
const names = ["tim", "ilias", "elie", "markus"];
const isEven = function (name) {
return name.length % 2 === 0;
};
const isOdd = function (name) {
return name.length % 2 !== 0;
};
const evenLengthNames = names.filter(isEven);
const oddLengthNames = names.filter(isOdd);
console.log(evenLengthNames);
console.log(oddLengthNames);
// Should output
// > ["elie", "markus"]
// > ["tim", "ilias"]
Use filter
to return an array of dogs.
const pets = [ {name: "fluffy", age: 2, type: "cat"}, {name: "fido", age: 1, type: "dog"}, {name: "nelly", age: 64, type: "parrot"}, {name: "benedict", age: 1, type: "sea cucumber"}, {name: "spot", age: 10, type: "dog"}, {name: "magic", age: 9, type: "cat"}]
var dogs = pets.filter(function(pet){
return pet.type==="dog";
})
console.log(dogs);
reduce
What:
Iterates over an array and turns it into one, accumulated value. In other words, you reduce a collection of values into one value. (In some other languages it is called fold
.)
How:
Your callback must take two arguments: (1) accumulated value/total (2) new/original array value. The value that your callback returns will be the new total
.
By default, total
will start out as the 0th element in the array and new
will be the element at index 1.
Example
const nums = [1,2,3,4];
const add = (total, new) => {
return total + new;
};
const sum = nums.reduce(add);
console.log(sum);
// Should output:
// > 10
// which is, 1 + 2 + 3 + 4
Alternative Initial Value
If you want to start with a different total
than 0th element, you can pass a second argument into filter
, and it will start by passing this value in as total
, and the 0th element as new
.
const nums = [1,2,3,4];
const add = (total, new)=> {
return total + new;
};
const sum = nums.reduce(add, 10);
console.log(sum);
// Should output:
// > 20
// which is, 10 + 1 + 2 + 3 + 4
Resources
Here are some good blog posts that break down map
, filter
, and reduce
.
Last updated
Was this helpful?