From irritation to iteration #2

A short iteration over Iteration functions

After covering the iteration basic concept on From irritation to iteration #1, it’s time for a short overview of all the array iteration methods we have. To make it simpler, I grouped similar functions with a line.


forEach

The forEach is the fastest way iterate. It executes the function over each element and doesn’t return a thing.

let arr = [1,2,3]
let arr2 = arr.forEach((item,index) => {
   item++;
});
// arr = [1,2,3]
// arr2 = undefined

let arr = [{v:1},{v:2},{v:3}];
arr.forEach((item,index) => {
   item.v++;
});
// arr ==> [{v:2},{v:3},{v:4}]

map

Create a transformation copy of each element from an array. Covered in length on the post about JavaScript array map.

[1,2,3].map((x)=>{
   return x * x;
});
// returns: 1,4,9

Find

Return the first true condition. If none of the condition is true, will return undefined. The iteration will exit the loop on the first true value. Null values are not skipped.

"sleep" === ['Ariel','wants','to','sleep',,'not','skip'].find(item => item[0] == 's');

undefuned === ['Ariel','wants','to','sleep','not','skip'].find(item => item == 'eat')
['Ariel','wants','to',,'not','skip'].find(item => item[1] == 's')
// Uncaught TypeError: Cannot read property '1' of undefined

findIndex

The same as “find”, just instead of the value, return the index. If no value had been found, it returns -1;

 1 === ['to','sleep'].findIndex(item => item == 'sleep');
-1 === ['to','sleep'].findIndex(item => item == 'eat');

every

Checks if all the elements answer the condition:

true  === ["zas","zad","zaf"].every((x) => x[1] == 'a');
false === ["zas","zzz","zaf"].every((x) => x[1] == 'a');

Exit the loop on first false value:

false === [{b:{c:1}},{},{b:{c:2}}].every((item,index) => {
   return item.b.c > 3;
});

Ignores null values

true === ["zaz",,"zaf"].every((x) => x[1] == 'a');

But falls on errors

[{b:{c:5}},{},{b:{c:2}}].every((item,index) => {
   return item.b.c > 3;
});

some

Same as “every”, check if at least one of the elements answer the condition. That’s why it stops on the first true value.

true === [{b:{c:5}},{},{b:{c:2}}].some((item,index) => {
   return item.b.c > 3;
});

Filter

Return a new set of elements that pass the condition.

arr = [1,2,3,4,5,6]
arr.filter((value) => {
   return value < 3;
});
// [1,2]

let me = [{name:'me',works:'overtime'},{name:'someone else',works:'less'}].filter((value) => {
   return value.works =='overtime';
});

reduce / reduceRight

Finally a different case: the reduction goes over each item, but also passes the result of the previously returned value.  This way you can create a function like SUM on lists.

[1,2,3,4,5].reduce((accumulator,currentItem,index,array) => {
   console.log(index + ': ' + accumulator + ' + ' + currentItem);
   return accumulator + currentItem;
});
//1: 1 + 2
//2: 3 + 3
//3: 6 + 4
//4: 10 + 5
// returns 15

If can pass the accumulator with starting value:

[1,2,3,4,5].reduce((accumulator,currentItem,index) => {
   console.log(index + ': ' + accumulator + ' + ' + currentItem);
   return accumulator + currentItem;
},100);

//0: 100 + 1
//1: 101 + 2
//2: 103 + 3
//3: 106 + 4
//4: 110 + 5
//115

Since it compares only the two values: the result and the current, we can do…

arr.reduce((accumulator,currentItem) => {
   return Math.max(accumulator,currentItem);
});

And just if you want to start from the end of the array and go backward:

[1,2,3,4,5].reduce((a,b,c,d) => {
   return a+ b;
},'0');
// 012345

[1,2,3,4,5].reduceRight((a,b,c,d) => {
   return a+ b;
},'0');
// 054321

entries

Return iterator of key-value objects

arr = ['a','b']
var iterator = arr.entries();
for (let[index, value] of iterator) {
   console.log(index + ': ' + value);
}
//0: a
//1: b

values

Return iterator, but without the index.

let array = [2,3,,5];
let iterator = array.values(); 
console.log(...iterator); 
// 2 3 undefined 5

array = new Array(5);
console.log(...array.values());
// undefined undefined undefined undefined undefined

array = new Array();
array[3] = 'd';
console.log(...array.values());
// undefined undefined undefined "d"

keys

gets the keys of the array to include empty elements

let array = [2,3,,5];
let iterator = array.keys(); 
console.log(...iterator); 
// 0 1 2 3

array = new Array(5);
console.log(...array.keys())
// 0 2 3 4 

array = new Array();
array[9] = 'd';
console.log(...array.keys())
// 0 1 2 3 4 5 6 7 8 9

I’ll be happy to get a useful example for all the last three :-/


Conclusion

The iteration was longer than expected, but It’s useful to know about the different options. Some are cool, some useful, and some are meant to satisfy the evil spirits. The last type is not documented in the post, but they are always there. Believe me, they are always there.