Introduction
When we start programming, we tend do create our own function with our own loop to manipulate arrays.
In reality, almost all OOP languages, including JavaScript, provide us methods to achieve it.
If you begin with JavaScript, this article should be really useful, for others, it will be a great reminder
Every
The every method allows us to test if all the elements of an array verify a condition.
This method returns true if all elements verify the test, otherwise, false.
The condition is a function.
For example, the following example will test if every 'human' in our array is an adult:
// The condition has to return a boolean
function condition (human) {
return human.age >= 18
}
var arr = [{
name: 'Thomas',
age: 19},{
name: 'Noé',
age: 17},{
name: 'Luc',
age: 20}]
console.log(arr.every(condition))
// Should output false
However, the some() method returns true if at least one element passes the test
Filter
The filter method creates and returns a new array with all elements that verify a condition.
The condition is a function.
The following example returns an array uniquely composed of adult:
function condition (human) {
return human.age >= 18
}
var arr = [{
name: 'Thomas',
age: 19},{
name: 'Noé',
age: 17},{
name: 'Luc',
age: 20}]
console.log(arr.filter(condition))
// Returns Thomas and Luc
Find
The method find() returns the first element in the array that verify the condition.
Otherwise, if no element verifies it, find() returns 'undefined'.
As usual, the condition is a function.
This example returns the first adult:
function condition (human) {
return human.age >= 18
}
var arr = [{
name: 'Thomas',
age: 19},{
name: 'Noé',
age: 17},{
name: 'Luc',
age: 20}]
console.log(arr.find(condition))
// Should returns Thomas
Map
The map method creates a new array with the return value of a function executed for each element of the calling array
This example increments the age of each human:
var arr = [{
name: 'Thomas',
age: 19},{
name: 'Noé',
age: 17},{
name: 'Luc',
age: 20}]
console.log(arr.map(function(element){
element.age += 1
return element
}))
Reduce
Last but not least, the reduce() method is for me the most tricky one.
The reduce method reduces an array to a single value by executing a provided function for each value of the array.
For each element, the return value is stored in an 'accumulator' that can be used in all the iterations.
The final return value of the reduce() method is this accumulator.
The accumulator should be initialized in the method call
Furthermore, the reducer function can take two other parameters:
- The current index
- The source array
This example returns the sum of ages:
function reducer (accumulator,element) {
return accumulator + element.age
}
var arr = [{
name: 'Thomas',
age: 19},{
name: 'Noé',
age: 17},{
name: 'Luc',
age: 20}]
console.log(arr.reduce(reducer,0))
The previous example is very simple, but the reduce() method is really powerful, you can achieve a lot of things with it.
Conclusion
Thank's for reading me, if you have any questions, ask them! 🧐
Top comments (22)
Your brackets in your arrays make me feel nauseous
and the white texts :D
Horrible. Truly horrible.
How did these make it into the language?
And it was already after people started caring about JS performance, not before :/
Can you explain your answer plis?
These garbage Array -> Array methods made it into the runtime, instead of something good like iterator adapters.
Now
numbers.filter(Number.isInteger).map(x=>x*2).reduce((a,b)=>a+b)
doesinstead of
numbers.filter(Number.isInteger).map(x=>x*2).reduce((a,b)=>a+b)
doingI didn't know how works this functions at low levels, but yes, this was a really good answer.
Maybe I think when you are not looking optimization of code and only legibility of it, use reduce, filter, etc. can have sense, no?
Legibility is extremely important.
I want everyone to write semantic, functional code without boilerplate.
But that depends on the language providing first-class support for it, instead of normalizing iterating 3 times instead of once and creating intermediate arrays.
I find using map/reduce/filter much more easier to read than this mumbo jumbo:
This wouldn't pass any code review in my office... We're writing code for the machine but humans will need to read that code too, and as far as I know, performance gains are minimal, and in the end, you have @babel plugin which transforms map/reduce/find and similar methods into for loops.
Would like to add that you should use those "advanced" array methods only if you know what you're doing, in the end, it's really important for the developer to know what's going under the hood and to know, at least, to write some of those examples in regular for/while loops.
I know exactly what they're doing, not just from practice but I've read the spec. One of the few ES specs I actually fully read.
These are just simplified versions of what is going on, what happens if we inline a crude implementation of the current spec vs what would be happening if it was done with transducers/iterator adapters, where all operations are applied to each item in order.
Also, the formatting in your quote is a bit strange.
It should look like this:
But yeah, if it isn't clear by now, I didn't advocate that anyone actually write either of the two unrolled codes in a project, they were just desugared explanations.
Truly reasons, I'm a junior developer and I'm used to using these methods because they are easy to use and their implementation too.
In countable occasions, I need to work in low-level loops to search optimization of code.
Thanx for sharing your knowledge it has been helpful and this babel package.
Writing it by hand it would probably look something like this:
But if you are writing application code with a framework, and not making your own library, you will probably have better returns if you look at your algorithms and data structures. It's very rare to be limited by loop performance in a frontend application.
If your collection is like 10 items, and your filtering and mapping predicates are complicated, there's usually no shame in applying a
filter
and then amap
separately.I agree depends on the case, some of the issues are related to maintainability other to performance issues, most of the cases is because some people is trying to overcomplicate things because some imaginary scalability issues.
Despite the fact the code is more performant, we should consider:
1 - Number of items
2 - Amount of operations
3 - Think in the different benefits coming from different worlds, FP, OOP, etc.
I saw more issues coming from extremely premature optimizations than performance issues, even with large datasets...
In addition, the code can be even readable
Again, it depends on the conditions,
Thank you for these tips :)
One question :
console.log(arr.every(condition))
// Should output true
It should not be false instead ? (There is at least one human under 18 in the list).
Totally!
Thanks for noticing, I've fixed it :)
Awesome dude
Thank you! this is a really handy page to bookmark
Just purely a question... But is using these convenience methods really more advanced than doing it manually without them? I can see arguments both ways...
Cool man,thanks. What about
some()
though?developer.mozilla.org/en-US/docs/W...
It tries the predicate on every item until it returns a truthy value.
If it reaches the end, returns false instead:
The opposite is
every()
:Finally some good examples of how this works, I've never really understood the image with food analogy
the every function was new to me . thanks
Thank u very much