Loop.js

Loop.js is a very small, but powerful, utility for looping over array-like objects. It enables the classical functional patterns like map, filter, fold and find with a single simple operation and features the ability to break out of the loop early.
The lo object (for loop-operations, or something) is passed into the callback function each lap in the loop. It provides access to the loop state and controls the looping.
var result = loop(arrayLike, defaultResult, function(lo){ var theCurrentItem = lo.item; var theCurrentIndex = lo.index(); var theResultSoFar = lo.result; //Starts with the value of the defaultResult parameter, and returned at end of iteration var isLastItemInTheArray = lo.isLast(); lo.stop(); //break out of loop });
The default result parameter is placed as the lo.result property. When looping ends, either because lo.stop() was called or because lo.index() has reached the length of the input, the lo.result property is returned from the loop function. Loopjs makes no special assumptions on lo.result, any iteration in the loop may change, replace or update lo.result as it sees fit.
If the first parameter is missing then this is used, so you can set the loop function to a property on an (array-like) object and do:
var obj = [1,2,3]; obj.loop = loop; var result = obj.loop(0, function(lo){ lo.result += lo.item; }
If the second parameter is also missing the lo.result property will be null on the first lap. If you loop the array for some side effect rather than the return value you can let it stay null. Or set it to something while looping.
var obj = [1,2,3]; obj.loop = loop; var result = obj.loop(function(lo){ //lo.result begins as null }
The lo.index() method return the current index in the array; this is sometimes useful.
var nums = [ 4, 11, 2, 26; ]; var sumOfEvenPositions = loop(nums, 0, function(lo){ if(lo.index() % 2 == 0){ lo.result += lo.item; } }); alert('Sum is ' + sumOfEvenPositions);
The lo.item property contains the item at the current position in the array. The lo.stop() method terminates the iteration.
var apes = [ 'Orangutang', 'Gorilla', 'Schimpanzee', 'Bonobo'; ]; var firstWithoutO = loop(apes, false, function(lo){ if(lo.item.toLowerCase().includes('o')){ lo.result = lo.item; lo.stop(); } }); if(firstWithout0){ alert('Found an ape without the letter o!'); }
Array-like objects have a length property and properties accessible through bracket-syntax:
var leng = arrayLike.length; var fourth = arrayLike[3];
Mapping arrays, i.e, creating a new array from the result of some operation done on each element in an another, is done with loopjs by letting the default result be an empty array and then push the result value in each lap of the loop.
var mapped = loop(inputArray, [], function(lo){ lo.result.push(someOperation(lo.item)); });
Filtering arrays, i.e, creating a new array containing some elements of another array, but not necessarily all, is done with loopjs by letting the default result be an empty array and then push just the values you want to retain.
var filtered = loop(inputArray, [], function(lo){ if(someCriterion(lo.item)){ lo.result.push(lo.item); } });
You can of course both filter and map in one go
var array = [ {name:'Angel', foundingMember:true}, {name:'Wolverine', foundingMember:false}, {name:'Iceman', foundingMember:true} ]; var founderNames = loop(array, [], function(lo){ if(lo.item.foundingMember){ lo.result.push(lo.item.name); } });
Folding an array, i.e, updating some result object somehow for each item in an array, is done with loopjs by setting the default result to some result object to update then update it for each item in the array.
var foldedResult = loop(inputArray, defaultResult, function(lo){ lo.result.updateSomehow(lo.item); });
Finding an element in an array is done with loopjs by checking each value in the loop and set the result to the correct value. The default result will then be returned if no lap in the loop sets the result.
var found = loop(inputArray, defaultResult, function(lo){ if(someCriterion(lo.item)){ lo.result = lo.item; lo.stop(); } });