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)
Output:
// Output
[ 'one' ]
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)
With this, we have the same first example output:
// Output
[ 'one' ]
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)
Output:
// Output
5
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)
Output:
// Output (The array returned by the .filter is: [7.3, 9.8, 7.1, 7.8, 8, 9, 7.5, 8.5])
8
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)
Output:
// Output
15
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
*/
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)
Output:
// Output
2
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)
Output:
// Output
1
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))
Output:
// Output
3
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))
Output:
// Output
3
Oldest comments (0)