JavaScript: Learn to filter array
JavaScript array filter method helps us to filter an array and create a new array without modifying the original array.
In my previous blog I wrote about JavaScript array map
method. In this article, I will write about filter
method.
filter
is a non-mutating method. Filter does not affect (modify) the original array if we use this method correctly. This (does not affect) does not mean that after applying filter
, the resulting array and original array elements will be the same. The resulting array will be a completely new array with different reference to the original array. The new array elements can be different than the original array. But, original array elements and reference will be unchanged.
filter
Like the map
method, the filter
method creates a new array with the same length from the original array. But, instead of creating an array with the same length as map
, the filter
method can create a new array with the same length or a smaller size array based on a condition.
filter
structure:
const resultingArray = oldArray.filter((currentValue, index, oldArr) => {
// return true or false
}, this);
filter
expects two parameters.
callback
function. This does the main job. We have to returntrue
to keep the element inresultingArray
andfalse
to exclude the element. We can use traditional function. OrES6
arrow
function. In our case,(currentValue, index, oldArr) => { // return true or false }
this is thecallback
function.this
argument. You can use it asthis
value in thecallback
function. It is optional and rarely used.
Now, callback
function accepts 3 arguments. These arguments are optional. But, the first two arguments are frequently used.
currentValue
. This is the element or value being processed in every loop iteration.index
. This represents the index ofcurrentValue
in the original array.array
. This is a rarely used argument. This represents the original array on which thefilter
method was applied.
After processing, filter
returns a new array. In our case, that array is resultingArray
. filter
creates this new array without modifying oldArray
. The resultingArray
contains elements for which callback
function returned true
.
Example:
const persons = [
{ name: "Jane", age: 19 },
{ name: "John", age: 21 },
{ name: "Rick", age: 17 },
{ name: "David", age: 22 },
];
const names = persons.filter(() => true);
// ES5 function syntax:
// const names = persons.filter(function () {
// return true;
// });
console.log(names);
// output:
// [
// { name: 'Jane', age: 19 },
// { name: 'John', age: 21 },
// { name: 'Rick', age: 17 },
// { name: 'David', age: 22 }
// ]
In this example, we have created an exact copy of the original array. In the filter
method, I am passing a function that returns true
in every iteration. As it returns true
for every element in the original array, every element is present in the new array. If we return false
for every element, then the new array would be empty.
If we wanted an array which will only contain those elements where person is more than 20 years old, then we could do the following:
const persons = [
{ name: "Jane", age: 19 },
{ name: "John", age: 21 },
{ name: "Rick", age: 17 },
{ name: "David", age: 22 },
];
const newPersons = persons.filter((person) => {
return person.age > 20;
});
// ES5 function syntax:
// const newPersons = persons.filter(function (person) {
// return person.age > 20;
// });
console.log(newPersons);
/* output: [ { name: 'John', age: 21 }, { name: 'David', age: 22 } ]
In this example, we have created a new array containing persons who are more than 20 years old. In the filter
method, I am passing a function which takes a person and returns true
if that person's age is more than 20 and otherwise returns false
. So, the filter
method will iterate the persons' array. When we return true
, the element in that iteration will be in the new array and when we return false
, the element in that iteration will not be in the new array.
Now in the first example, I used shorthand syntax to return true
and in the second example, I returned true
and false
explicitly.
We can use normal callback
function instead of ES6
arrow
function. But, arrow functions are more readable.
I will now share another example with index
and array
in callback
function:
const persons = [
{ name: "Jane", age: 19 },
{ name: "John", age: 21 },
{ name: "Rick", age: 17 },
{ name: "David", age: 22 },
];
const newPersons = persons.filter(
(person, index, array) => person.age > 20 && index < array.length / 2
);
// ES5 function syntax:
// const newPersons = persons.filter(function (person, index, array) {
// return person.age > 20 && index < array.length / 2;
// });
console.log(newPersons);
// Output: [ { name: 'John', age: 21 } ]
In this example, I am creating a new array with only persons who are more than 20 years old and are in the first half of the array. So, David is not in the resulting array despite being more than 20 years old as he is in the second half of the array.
All modern browsers support filter
. You can find complere reference here
When not to use the filter method
When you need to modify an array, filter
will not be able to do the job in that case. filter
returns the same element for which callback
function returns true
.
So, when you need to modify the array elements, you can use map
.
You should learn about all array methods to use them appropriately in your codebase.
Why filter is more readable
Suppose, you are creating a new array of persons who are more than 20 years old like our second example with traditional for
loop. Then, the code should be like this:
let newPersons = [];
for (let i = 0; i < persons.length; i++) {
if (persons[i].age > 20) {
newPersons.push(persons[i]);
}
}
You need to go through the whole code to understand that I am creating a new array with persons who are more than 20 years old. You will also have to check if I have written a break
or continue
statement to skip any particular value or not. You will also have to check if I am modifying the elements of the array or not.
But, in my filter
example, as soon as you see a filter
method, you know that I am creating a new array with the same type of elements as the original array. You will be sure that in the resulting array, elements structure or type is not modified. Also, the main logic of elements which will be in the resulting array is very easy to find.
const newPersons = persons.filter((person) => {
return person.age > 20;
});
When we use filter
, we can focus more on logic cause it's purpose is defined.
Conclusion
The filter
method has a specific purpose. That purpose is: creating a new array with elements that pass a specific condition. Whenever we need this functionality in our code, we should be using filter
for better readability and maintainability.