JavaScript array methods 2/3 - iterating arrays 
Tags: javascript, tutorial, webdev, beginners
Published: 2021-08-17 12:19:59

As we know, arrays are collections of elements. JavaScript arrays have something named iteration methods - these methods operate on every element of the collection and can help us with creating new arrays based on individual entries of our original array or just simply do something with every single element. In this part of our JavaScript array methods series, we are going to cover them in deep.

-----

## Looping through an array

Looping (or iterating) through an array in most languages is commonly done using a for-loop. JavaScript is not different.

```javascript
const images = [
  'https://image-cdn.com/my-image-1.jpeg',
  'https://image-cdn.com/my-image-2.jpeg',
  'https://image-cdn.com/my-image-3.jpeg',
];

for (let i = 0; i < images.length; ++i) {
  console.dir(images[i]);
}
```

This code is going to output every single URL in the images array. As you see, our iteration is working, nothing special. It may look familiar to you if you worked with languages other than JavaScript.

However, it's not the only way to loop through our array. The Array prototype has implemented a `forEach` method, which calls a callback on every element of an array.

```javascript
const images = [
  'https://image-cdn.com/my-image-1.jpeg',
  'https://image-cdn.com/my-image-2.jpeg',
  'https://image-cdn.com/my-image-3.jpeg',
];

images.forEach((image) => console.dir(image));
```

> **NOTE**. You can access the index of the current element by passing a second argument to the function inside `forEach`.

The result is the same - we've printed every element of this array. Although there is a difference between a classic for loop and a forEach - performance. forEach may be more convenient, but it's slower, so when you're dealing with big arrays you shouldn't use it.

![Looping through a 10 000 elements array using three different methods.](https://blog.danieo.me/content/images/2021/08/photo_2021-08-15_16-15-22.jpg)

In these benchmark results, you can see that there is a third method of iteration, which is a bit faster than `forEach` and more friendly than a classic `for` loop - I'm talking about `for...of`. It was introduced after for and forEach and works...

```javascript
const images = [
  'https://image-cdn.com/my-image-1.jpeg',
  'https://image-cdn.com/my-image-2.jpeg',
  'https://image-cdn.com/my-image-3.jpeg',
];

for (const image of images) {
  console.dir(image);
}
```

...the same way - I mean, it produces the same result. Being slightly more performant than `forEach` it's a better choice in most cases. Furthermore, opposite to `forEach`, it can be controlled with statements like break, but this article is not about loops, so we're going to stop talking about `for...of`.

## Modify all elements of an array - mapping arrays

Sometimes you'll need to transform every single element of your array and create a new array with these elements. In this case, `map` is the remedy. It simply runs a callback on every element and then creates a new array from the results.

```javascript
const names = ['dave', 'emma', 'alan', 'simon', 'stacy'];
const capitalizedNames = names.map((name) => {
  return name[0].toUpperCase() + name.slice(1);
});

console.dir(capitalizedNames); // Output: ["Dave", "Emma", "Alan", "Simon", "Stacy"]
```

This example is going to capitalize the first letter of every word in the array and return a new array consisting of capitalized words.

> **NOTE**. You can access the index of the current element by passing a second argument to the function inside `map`.

With using `map` comes one thing that you need to remember - the resulting array is the same length as the original array and every missing element is just changed to undefined. It can occur in a case like this:

```javascript
const array = ['1', '6', '17', 'boo!', '32'];

const numbers = array.map((x) => {
  const n = +x; // It's just a short way to cast a string into number
  if (!isNaN(n)) {
    return n;
  }
});

console.dir(numbers); // Output: [1, 6, 17, undefined, 32]
```

In this example, we are converting an array of numeric strings to an array of numbers. There is only one problem, when conversion fails we get a NaN, and our statements under the condition are never called so this iteration never returns a value, in this case, map is going to return an `undefined` for that element.

### Mapping and flattening?

Now, as we already covered map, let's talk about `flatMap`, which works like map followed by `flat`. Let's assume we have a text as an array of sentences and we want to tokenize it.

```javascript
const text = [
  "I've gotta go. You'll find out in thirty years.",
  "That's a great idea. I'd love to park.",
  "What the hell is a gigawatt? Lorraine, are you up there?",
];

const sentenceToken = text.map((sentence) => sentence.split(" ")).flat();
console.dir(sentenceToken); // Output: [ "I've", "gotta", "go.", "You'll", "find", "out", "in", "thirty", "years.", "That's", … ]
```

> **NOTE**. It's not a proper way to tokenize strings. It's a very simplified example to show how `flatMap` works.

We map our text array and create an array of arrays containing single word tokens, then we flatten that array to get a one-dimensional array with all tokens. Simple, right? But do you know that we can do it better using `flatMap`?

```javascript
const text = [
  "I've gotta go. You'll find out in thirty years.",
  "That's a great idea. I'd love to park.",
  "What the hell is a gigawatt? Lorraine, are you up there?",
];

const sentenceToken = text.flatMap((sentence) => sentence.split(" "));
console.dir(sentenceToken); // Output: [ "I've", "gotta", "go.", "You'll", "find", "out", "in", "thirty", "years.", "That's", … ]
```

It produces the same result, is a bit shorter, and is also slightly more performant.

![Benchmark result - flatMap is more performant than map + flat](https://blog.danieo.me/content/images/2021/08/Screenshot-2021-08-15-at-19-44-06-JSBEN-CH-Benchmarking-for-JavaScript--.png)

The choice should be obvious.

## Reducing arrays

Reducing is a process where an array is reduced to a single value, it is achieved by calling a **reducer function** on every element. A reducer function can take four arguments:

* **Accumulator** - it contains a value that is passed to every iteration, and after the final iteration, it becomes the value returned by reduce.
* **Current value** - as the name says, it's the value of the current element.
* **Current index** - an array index of the current iteration.
* **Source array** - the array on which reduce is called.

Now some of you may wonder "ok, but where can I use this method?". Let's assume we have an array of numbers and we want to count the sum of its elements. It can be done using a for and adding every element of this array to a variable, but also it can be done using reduce.

### Counting sum of array elements

```javascript
const numbers = [77, 94, 668, 371, 2, 194, 54, 674, 7, 213, 26];
const sum = numbers.reduce((acc, value) => acc + value);
console.dir(sum); // Output: 2380
```

Reduce can also be used to find the minimal and maximal value in an array.

### Finding minimum and maximum in an array

```javascript
const numbers = [77, 94, 668, 371, 2, 194, 54, 674, 7, 213, 26];
const min = numbers.reduce((acc, value) => acc < value ? acc : value);
console.dir(min); // Output: 2
```

```javascript
const numbers = [77, 94, 668, 371, 2, 194, 54, 674, 7, 213, 26];
const max = numbers.reduce((acc, value) => acc > value ? acc : value);
console.dir(max); // Output: 674
```

But hey! JavaScript has methods like min and max in its Math object, can't we just use them? Of course, we can! Although, surprisingly, using reduce is faster. On a 10 000 elements array the result is as follows:

![Benchmark results - Finding arrays minimal value using reduce is faster than Math.min](https://blog.danieo.me/content/images/2021/08/Screenshot-2021-08-17-at-11-01-21-JSBEN-CH-Benchmarking-for-JavaScript--.png)

Let's check it also on a smaller array (with 10 elements).

![Benchmark results - Finding arrays minimal value using reduce is faster than Math.min](https://blog.danieo.me/content/images/2021/08/Screenshot-2021-08-17-at-11-04-25-JSBEN-CH-Benchmarking-for-JavaScript--.png)

### Grouping objects in an array

Another very useful case for `reduce` is grouping objects in an array by their properties. Let's take a look at this example:

```javascript
const animals = [
  { name: "Dog", group: "mammals" },
  { name: "Eagle", group: "birds" },
  { name: "Tiger", group: "mammals" },
  { name: "Dolphin", group: "mammals" },
  { name: "Frog", group: "amphibians" },
  { name: "Parrot", group: "birds" },
];

const groupsSchema = {
  mammals: [],
  birds: [],
  amphibians: [],
};

const groups = animals.reduce((acc, value) => {
  acc[value.group].push(value);
  return acc;
}, groupsSchema);

console.dir(groups);
```

In this example we got an array of animals, every animal has its name and the group it belongs to. Using `reduce` we group them into separate arrays based on the value of `group`. If you haven't noticed - we can pass an initial value for our accumulator by passing a second argument to `reduce`.

### Reducing backward?

`reduce` is going to iterate from the lowest index to the highest (from start to end). However, sometimes we may need to reduce an array backward - in that case, we can use `reduceRight`. It works identically to reduce, only the iteration starts from the highest index and goes to the lowest index.

```javascript
const array = [[1, 2], [3, 4], [5, 6]];
const result1 = array.reduce((acc, value) => acc.concat(value));
const result2 = array.reduceRight((acc, value) => acc.concat(value));
console.dir(result1); // Output: [1, 2, 3, 4, 5, 6]
console.dir(result2); // Output: [5, 6, 3, 4, 1, 2]
```

## Check if every element fulfils your condition

To check if all of the elements of an arrays are meeting our condition we can use `every`. This method runs a test on every element. If everything will pass, then it returns `true` - if not it returns `false`.

```javascript
const positives = [1, 56, 17, 592, -5, 9];
const isEveryPositive = positives.every((value) => value > 0);
console.dir(isEveryPositive); // Output: false
```

```javascript
const positives = [1, 56, 17, 592, 5, 9];
const isEveryPositive = positives.every((value) => value > 0);
console.dir(isEveryPositive); // Output: true
```

> **NOTE**. The test function also accepts a second argument after value, it's the index of the current element.

## Check if any element fulfils your condition

When you want to check if one or more element pass your test, you can use `some`. It's similar to `every`, but it expects only **some** values to pass the test.

```javascript
const positives = ["Hammer", "Screwdriver", null, "Wrench"];
const isSomeNull = positives.some((value) => value === null);
console.dir(isSomeNull); // Output: true
```

```javascript
const positives = ["Hammer", "Screwdriver", "Pliers", "Wrench"];
const isSomeNull = positives.some((value) => value === null);
console.dir(isSomeNull); // Output: false
```

> **NOTE**. Similar to every you can also access the index of the current element by passing a second argument to the test function.

## Filtering arrays

Removing elements that don't fulfill our conditions can be pretty handy. filter creates a new array consisting of elements that pass our test.

```javascript
const numbers = [456, 1837, 123, 416, 12, 312, 7];
const filtered = numbers.filter((value) => value >= 100);
console.dir(filtered); // Output: [456, 1837, 123, 416, 312]
```

### Removing duplicates from an array

```javascript
const pets = ["Dog", "Cat", "Hamster", "Dog", "Canary"];
const filtered = pets.filter((value, index, array) => array.indexOf(value) === index);
console.dir(filtered); // Output: ["Dog", "Cat", "Hamster", "Canary"]
```

> **NOTE**. this method is not performant on big arrays. With bigger arrays consider using the ES6 way to create unique arrays.

```javascript
const pets = ["Dog", "Cat", "Hamster", "Dog", "Canary"];
const filtered = [...new Set(pets)];
console.dir(filtered); // Output: ["Dog", "Cat", "Hamster", "Canary"]
```

This will create a `Set` from our array and then convert it back to a classic array. Sets are collections like array but they have a unique constraint - they don't accept duplicates and every value is unique. Below is a test comparing these methods on a 1000 elements array.

![Benchmark result - creating a set of a big array is more performant than filtering duplicates](https://blog.danieo.me/content/images/2021/08/Screenshot-2021-08-17-at-13-12-12-JSBEN-CH-Benchmarking-for-JavaScript--.png)

and on a small 20 elements array.

![Benchmark result - filter is more performant on small arrays than creating a Set](https://blog.danieo.me/content/images/2021/08/Screenshot-2021-08-17-at-13-12-58-JSBEN-CH-Benchmarking-for-JavaScript--.png)

-----

And that's all! We are almost at the end of this short series! The last part is going to cover searching in arrays. For now, take care! If you like my work consider visiting [my blog](https://blog.danieo.me) signing up for my newsletter.