DEV Community

Pablo Felipe
Pablo Felipe

Posted on

Count Certain Elements of an Array in JavaScript

An yellow background with the following text: "Array in JavaScript" inside a square brackets symbol

Introducing the .filter method that can be used literally to filter array elements based on a condition, we can use it in addition to the .length property to count certain elements of an array. The condition of the .filter method is provided by a function, passed as parameter. Also, we will introduce the .reduce method that executes a function for each element in the array and return a single value.

The function passed as parameter can be either an arrow function or a common function as a callback function, and it will dictate what elements the .filter will add or not to the returned array or what exactly the .reduce method will do for each elements in the array.

Count Certain Elements of an Array in JavaScript using the .filter Method

The .filter is a method of the Array entity that returns a new array filtered by the provided condition. Returning a new array, means that the original array which the method is called will stand immutable. For example, if we want all elements that is equal to the value 'one' in an array, we can use the .filter as below:

// Input
let array = ['one', 'two', 'three', 'four', 'five']
array = array.filter(element => element == 'one')
console.log(array)
Enter fullscreen mode Exit fullscreen mode

Output:

// Output
[ 'one' ]
Enter fullscreen mode Exit fullscreen mode

As expected, the .filter method returned an array based on the element == 'one' condition. So if the actual element of the array is equal to 'one', then the filter will add this element to the returned array.

But what is happening inside the .filter method? We can see better by using a common function structure to the condition() function:

// Input
let array = ['one', 'two', 'three', 'four', 'five']
array = array.filter(function condition(element) {
    if (element == 'one') return true
    return false
})
console.log(array)
Enter fullscreen mode Exit fullscreen mode

With this, we have the same first example output:

// Output
[ 'one' ]
Enter fullscreen mode Exit fullscreen mode

The condition() function receives an element as parameter, and if this element is equals to a certain value, in this case 'one', it returns true and if not, returns false. So, the .filter method add any of the element that the condition results in true; as the original array has only the first element as one, the .filter return only one element.

Note that the condition() function is declared inside the .filter method. If you declare it outside and call it inside the .filter, it will not work, because the element is part of the callback scope.

Basically, a callback function is a function passed as parameter to another function which is called "outer function". The callback function will be called by the outer function to do something; in the case of the .filter method, it will call the condition() callback function to filter the array based on its condition.

Back to our objective, the .filter will finally return a new array that have array.length elements, which each one is an element that the callback function returned a value equivalent to true. As we want to count these filtered elements, we can easily do this with the .length property.

The .length is as property of the Array entity that returns the number of elements in an array. This number is always greater than the highest index in that array, because the first element is always on the index equals to 0.

// Input
let array = [1, 2, 3, 4, 5]
console.log(array.length)
Enter fullscreen mode Exit fullscreen mode

Output:

// Output
5
Enter fullscreen mode Exit fullscreen mode

The number of elements in the array is 5. 5 is a number greater than the index of the value 5, that is 4.

Putting all together, as an example we can use the following: How to get the number of all test notes of an school, that are greater than seven? The array of the test notes is in the example.

// Input
let notes = [7.0, 6.7, 7.3, 9.8, 5.6, 7.1, 7.8, 6.2, 8.0, 9.0, 4.5, 6.9, 7.5, 8.5, 6.4]
greaterThanSeven = notes.filter(value => value > 7)
console.log(greaterThanSeven.length)
Enter fullscreen mode Exit fullscreen mode

Output:

// Output (The array returned by the .filter is: [7.3, 9.8, 7.1, 7.8, 8, 9, 7.5, 8.5])
8
Enter fullscreen mode Exit fullscreen mode

So, 8 is the number of notes that are greater than 7 of all 15 notes in the original notes array.

Now, as another option we can use the .reduce Array entity method. This method is used to execute a callback function (as well as the .filter) on each element of the array, but it will finally return a single value.

A simple example to the .reduce working, is the sum of all element in an array:

// Input
let array = [1, 2, 3, 4, 5].reduce((previous, current) => previous + current)
console.log(array)
Enter fullscreen mode Exit fullscreen mode

Output:

// Output
15
Enter fullscreen mode Exit fullscreen mode

But this method can be used in other way, that is by passing the initial value. In the previous example, we can see that the previous begin with the first index element in the array, being the callback function, this way:

/*
previous + current = result
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15 -> final result
*/
Enter fullscreen mode Exit fullscreen mode

This sum is working correctly because if we don't pass a second parameter (as the callback function is the first parameter) to the .reduce method, it will consider previous as the first element of the array in the first iteration.

But if we want to count certain elements in the array? We cannot use the first element as the previous, because it could result in a wrong value. The example below is about counting how many 2 numbers are in the array:

// Input
let array = [1, 2, 3, 4, 5].reduce((sum, value) => (value == 2 ? sum + 1 : sum))
console.log(array)
Enter fullscreen mode Exit fullscreen mode

Output:

// Output
2
Enter fullscreen mode Exit fullscreen mode

As we can see, the result is 2, but the correct answer is 1. This happened because the sum is being initialized with the first element 1, as we don't passed any other parameter beyond the callback function. To do the correction, we can just pass a 0 as the second .reduce parameter:

// Input
let array = [1, 2, 3, 4, 5].reduce((sum, value) => (value == 2 ? sum + 1 : sum), 0)
console.log(array)
Enter fullscreen mode Exit fullscreen mode

Output:

// Output
1
Enter fullscreen mode Exit fullscreen mode

This way, the .reduce is making sum + 1 every time that the current element is equal to 2, with the sum being initialized with 0.

Extra

As a plus, instead of using all theses logics every time that we need to count certain elements in an array, we can use the .prototype Array entity property to write custom methods or properties to this entity.

To make a .countCertainElements method to the Array entity, we can use the following structure:

// Input
// Declaring the prototype .countCertainElements method
Array.prototype.countCertainElements = function(value){
    return this.filter(arrayElement => arrayElement == value).length
}
let array1 = [1, 2, 2, 2, 3, 4, 5]
console.log(array1.countCertainElements(2))
Enter fullscreen mode Exit fullscreen mode

Output:

// Output
3
Enter fullscreen mode Exit fullscreen mode

And the same can be done for the .reduce:

// Input
// Declaring the prototype .countCertainElements method
Array.prototype.countCertainElements = function(value){
    return this.reduce((sum, element) => (element == value ? sum + 1 : sum), 0)
}
let array1 = [1, 2, 2, 2, 3, 4, 5]
console.log(array1.countCertainElements(2))
Enter fullscreen mode Exit fullscreen mode

Output:

// Output
3
Enter fullscreen mode Exit fullscreen mode

Oldest comments (0)