DEV Community

Ernesto Bellei for hund

Posted on

Array iteration examples

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.

Map

📄 MDN REference

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
Enter fullscreen mode Exit fullscreen mode

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: 👦, 👩, 👱
Enter fullscreen mode Exit fullscreen mode

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>
);
Enter fullscreen mode Exit fullscreen mode

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 use forEach() 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
Enter fullscreen mode Exit fullscreen mode

Every

📄 MDN Reference

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
Enter fullscreen mode Exit fullscreen mode

Find

📄 MDN Reference

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",
 *  },
 */
Enter fullscreen mode Exit fullscreen mode

Filter

📄 MDN Reference

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",
 *  }
 * ]
 */
Enter fullscreen mode Exit fullscreen mode

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">
Enter fullscreen mode Exit fullscreen mode

Sort

📄 MDN Reference

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Sorting alphabetical order

const words = ["alpha", "beta", "gamma"];

const sortedWords = events.sort((current, next) => current > next);

// expected:
// sortedWords: alpha, bbeta, gamma
Enter fullscreen mode Exit fullscreen mode

Reduce

📄 MDN Reference

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);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The spread operator

📄 MDN Reference

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']
Enter fullscreen mode Exit fullscreen mode

👨‍🏫 If we need to create one function to add items from an array we will use the ... spread operator whereas we will use a filter 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'
 * }
Enter fullscreen mode Exit fullscreen mode

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.`;
};
Enter fullscreen mode Exit fullscreen mode

Top comments (0)