This article tries to examine different real-life use cases which can be solved with Array
methods.
For a technical definition of each method, every section has a link to the official 📄 MDN Reference. This article is about examples and tips, not documentation.
Table of contents | |
---|---|
map() |
|
every() |
|
find() |
|
filter() |
|
reduce() |
|
sort() |
|
every() |
|
BONUS | The spread iterator ... |
Map
map()
is probably the most used and versatile method out there, as MDN states:
Returns a new array containing the results of invoking a function on every element in the calling array.
Execute the same function on every item of the array
👨🏫 You have a bunch of data and want to run the same action on all of them.
const numbers = [1, 2, 3];
const numbersPlusOne = numbers.map((number) => number + 1);
// expected:
// numbersPlusOne: 2, 3, 4
Convert an array of configuration options to Class Instances
👨🏫 You have an array of different arguments and want to change them into Class Instances.
const peopleOptions = [
{
name: "Antonio",
age: 13,
height: 1.83,
},
{
name: "Federico",
age: 54,
height: 0.9,
},
{
name: "Ernesto",
age: 27,
height: 2.2,
},
];
const people = peopleOptions.map((personOptions) => new Person(personOptions));
// expected:
// people: 👦, 👩, 👱
In React, render a list of whatever object
👨🏫 You want to render some UI elements using React.
// ... some React Component logic
const list = ["milk", "eggs", "cucumbers"];
return (
<ul>
{list.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
Bonus Track: In combination with Promise.all()
In combination with Promise.all()
can be used to wait for multiple async
operations BUT:
⚠️ When using
Promise.all()
the asynchronous functions are not executed in the same order as the initial array. If you have asynchronous functions which need to run in an exact sequence (ae. update a record after a creation) you must useforEach()
which will wait for each loop to be complete before continuing.⚠️ Even though the asynchronous functions are executed in random order the output results array will preserve the same order as the initial array.
const membersName = ["Antonio", "Ernesto", "Federico"];
const membersAge = await Promise.all(
members.map(async (memberName) => {
const age = await getAgeFromDbWhereNameIs(memberName);
return age;
})
);
// Wait untill Promise is fullfilled
// expected:
// membersAge: 13, 27, 54
Every
This method can be used to check whether all elements inside an array fulfill a specific requirement.
This method is the only one that does not return an array whereas a boolean.
👨🏫 You want to filter an array and detect which items for a specific order are in stock and ready for shipment.
const order = [
{
name: "Tea Shirt",
availableStock: 10,
},
{
name: "Jeans",
availableStock: 0,
},
{
name: "Filp Flops",
availableStock: 3,
},
];
const isOrderReadyForShipment = order.every(
(product) => product.availableStock > 0
);
// expected:
// isOrderReadyForShipment: false
Find
This method can be used to find the first element which matches a condition.
⚠️ This method will only return THE FIRST matching element, if there is more than one element that matches the condition it will be ignored.
👨🏫 You have a list of posts and want to get the first matching the tag yes.
const posts = [
{
title: "How to open your mind using a knife",
author: "Ernesto",
tag: "yes",
},
{
title: "Let your dog do wathever he wants",
author: "Federico",
tag: "no",
},
{
title: "How to escape from a glass cage",
author: "Ernesto",
tag: "yes",
},
];
const yesPost = posts.find((post) => post.tag === "yes");
/**
* expected:
* yesPost: {
* title: "How to open your mind using a knife",
* author: "Ernesto",
* tag: "yes",
* },
*/
Filter
Now that you are a find
expert we can bring it to the next level. The filter
method works the same as find
but it returns all matching values instead.
It can be used for a couple of things such as...
Filter values that match certain criteria
👨🏫 You have a list of posts and want to get all posts matching the tag yes.
const posts = [
{
title: "How to open your mind using a knife",
author: "Ernesto",
tag: "yes",
},
{
title: "Let your dog do wathever he wants",
author: "Federico",
tag: "no",
},
{
title: "How to escape from a glass cage",
author: "Ernesto",
tag: "yes",
},
];
const yesPosts = posts.filter((post) => post.tag === "yes");
/**
* expected:
* yesPost: [
* {
* title: "How to open your mind using a knife",
* author: "Ernesto",
* tag: "yes",
* },
* {
* title: "How to open your mind using a knife",
* author: "Ernesto",
* tag: "yes",
* }
* ]
*/
Clean an array from unwanted/falsy values
When working with React you might have noticed that when using classes to style an is-active
state sometimes you get dirty class names:
-
" undefined"
; -
"false null another-class-name"
.
👨🏫 You want to create a function to clean classNames from unwanted/falsy values.
const active = false;
return <div className={[active && "is-active", "round-borders"].join(" ")} />;
// expected <div class="false round-borders">
const css = (...classNames: (string | undefined | null | false)[]) =>
classNames.filter((className) => !className).join(" ");
return <div className={css(active && "is-active", "round-borders")} />;
// expected <div class="round-borders">
Sort
You have an array with 3 numbers [3, 18, 7, 18]
which need to be sorted in "ASCending" order.
The sort method compares values two by two and depending on the value obtained subtracting one from another decide whether:
Condition | New order | ||
---|---|---|---|
< 0 |
3 - 18 = -15 | keep 3 before 18 | [3, 18, 7, 18] |
> 0 |
18 - 7 = +11 | exchange 18 with 7 | [3, 7, 18, 18] |
= 0 |
18 - 18 = 0 | keep the same order | [3, 7, 18, 18] |
const numbers = [3, 18, 7];
const sortedNumbers = numbers.sort((current, next) => curremt - next);
// expected:
// sortedNumbers: 3, 7, 18
The same method works with any kind of data:
Sorting dates
const events = [
{ name: "Social pic-nic", date: "12/11/2022" },
{ name: "Karate Lesson", date: "3/8/2022" },
{ name: "Pay Rent", date: "23/12/2022" },
];
const sortedEvents = events.sort((current, next) => current.date > next.date);
// expected:
// sortedNumbers: Karate Lesson, Social pic-nic, Pay Rent
Sorting alphabetical order
const words = ["alpha", "beta", "gamma"];
const sortedWords = events.sort((current, next) => current > next);
// expected:
// sortedWords: alpha, bbeta, gamma
Reduce
Reduce is so far the most complex but the most versatile method.
That said it can be used to run a function through every element of the array.
Get the sum of a specific item key value inside an array
👨🏫 Calculate the subtotal of all items inside a cart.
const cart = [
{
name: "T-shirt",
qty: 1,
price: 10000,
},
{
name: "Hat",
qty: 2,
price: 20000,
},
{
name: "T-shirt",
qty: 1,
price: 15000,
},
];
const cartSubtotal = cart.reduce((cartSubtotal, item) => {
const itemSubtotal = item.qty * item.price;
return cartSubtotal + itemSubbtotal;
}, 0);
Manipulate data inside objects
In combination with Object.keys()
the reduce
method can be used to loop through javascript objects and manipulate their data.
👨🏫 Create two functions to remove or add given quantities of items from a cart.
⚠️ This
cart
variable is different from the previous. Previous one was an array, this is an object.
const cart = {
productCodeSample1234: {
name: "T-shirt",
qty: 1,
price: 10000,
},
sampleuniqueCode1234: {
name: "Hat",
qty: 2,
price: 20000,
},
otherCodeSample01234: {
name: "T-shirt",
qty: 1,
price: 15000,
},
};
const addToCart = (uniqueCode: string, qty: number | undefined = 1) =>
Object.keys(cart).reduce((cart, cartProductCode) => {
if (cartProductCode === uniqueCode) cart[uniqueCode].qty += qty;
return cart;
}, cart); // add a given qty of products from your cart
const removeFromCart = (uniqueCode: string, qty: number | undefined = 1) =>{
const updateItemsQuantity = Object.keys(cart).reduce((cart, cartProductCode) => {
if (cartProductCode === uniqueCode) cart[uniqueCode].qty -= qty;
return cart;
}, cart); // remove a given qty of products from your cart}
const updateItemsQuantity.filter(item => item.qty > 0); // remove ites with 0 or negative qty
The spread operator
Even though the spread operator is not directly related to array methods, rather than to all generic iterable objects, I thought it would have been useful to mention it in this compendium.
Add elements to an array
The ...
spread operator means: repeating the items of an array (or the object keypairs) inside a new iterable object.
This allows us to clone an array inside another one while we add new items in between.
const lunchbbox = ["apple", "banana"];
const pencilCase = ["pen", "pencil"];
const backpack = ["tablet", ...lunchBox, "laptop", ...pencilCase];
// expected:
// backpack = ['tablet', 'apple', 'banana', 'laptop', 'pen', 'pencil']
👨🏫 If we need to create one function to add items from an array we will use the
...
spread operator whereas we will use afilter
method to remove them.
Override a default configuration
When you create a slider you probably set some default options (such as animation speed, and transition type ...) which can be overridden by another developer to customize it.
interface SliderConfig {
animationSpeed: number;
transitionType: "fade" | "slide",;
}
const defaultConfig: SliderConfig = {
animationSpeed: 0.2,
transitionType: 'slide'
};
const applyUserConfig = (userConfig: SliderConfig) => {
return {
...defaultConfig,
...userConfig,
};
};
const sliderConfig = applyUserConfig({
animationSpeed: 0.4
})
/**
* expected:
* {
* animationSpeed: 0.4
* transitionType: 'slide'
* }
Repeat arguments of concatenated complex functions
This is a complex and probably uncommon case but it can be useful to store it somewhere in your mind when difficult times will come.
The spread operator can be used to spread function arguments with a function that accepts a subset of given args. Its only need is to make the code more readable BUT it will require more attention because it reduces how freely you can edit and change the structure of your functions...as I said store it somewhere in your mind when difficult times will come.
const createAChocolateEgg = (
height: number,
width: number,
chocolateType: string
) => {
return `A ${chocolateType} chocolate egg, height: ${height}, width: ${width}`;
};
const createADecoratedChocolateEgg = (
color: string,
...chocolateEggArgs: [number, number, string]
) => {
return `${createAChocolateEgg(
...chocolateEggArgs
)} whith ${color} sprinkles on it.`;
};
Top comments (0)