It's not always the absolute best choice to prioritize performance above all else. Is shaving off 1-2 ms from a task that only runs once a minute really worth it? For me, readability and error prevention take precedence.
When For is faster and Map is cleaner, how do you determine which one is the better option?
Cleaner code is preferred until actual performance issues arise. In such cases, it's important to debug where these performance problems are coming from instead of blindly refactoring and "optimizing."
However, your code may have a larger performance issue beyond just using for
versus map
. The problem lies within your approach involving nested loops.
Your current implementation requires iterating through all products for each category.
let categoriesDataArray = [];
if(!this.props.categoriesIsFetching){
categoriesDataArray = this.props.categories.map(category => {
return {
title: category.title,
data: this.props.products.filter(product => product.category_id === category._id)
}
});
}
Sometimes this approach works fine. It's simple and expressive, but as your arrays grow in size, the execution time will significantly increase. In such scenarios, adopting a different approach would be more beneficial than debating between for-loops or Array#map.
You can achieve the same task by iterating over each array once and utilizing a map operation, resulting in a runtime of O(n+m)
rather than O(n*m)
.
let categoriesDataArray = [];
if(!this.props.categoriesIsFetching){
const productsByCategoryId = {};
categoriesDataArray = this.props.categories.map(category => {
return {
title: category.title,
data: productsByCategoryId[category._id] = []
}
});
this.props.products.forEach(product => {
if(product.category_id in productsByCategoryId)
productsByCategoryId[product.category_id].push(product);
});
}
or as loops:
let categoriesDataArray = [];
if(!this.props.categoriesIsFetching){
const productsByCategoryId = {};
for(let i=0; i<this.props.categories.length; ++i){
let category = this.props.categories[i];
let data = [];
productsByCategoryId[category.__id] = data;
categoriesDataArray[i] = {
title: category.title,
data: data
}
}
for(let j=0; j<this.products.categories.length; ++j){
let product = this.products.categories[j];
if(product.category_id in productsByCategoryId){
productsByCategoryId[product.category_id].push(product);
}
}
}