JAVASCRIPT   95

Iterators js

Guest on 31st May 2022 01:58:27 AM

  1. /**
  2.  * @author Tom
  3.  */
  4.  
  5. /**
  6.  * Invokes the iterator for the number times and returns a result of the iterator.
  7.  * The iterator receives one argument, the number of the iteration.
  8.  * @param {Number} number
  9.  * @param {Object} iterator
  10.  * @return {Object}
  11.  */
  12. function times(number, iterator) {
  13.         for (var i = 0; i < number; i++) {
  14.                 iterator(i);
  15.         }
  16.         return iterator.result;
  17. }
  18.  
  19. /**
  20.  * For each item of the list invokes the iterator with two arguments:
  21.  * the item of the list and index of the item.
  22.  * The list is an array like object: an array,
  23.  * or an object with numeric property length (e.g. arguments).
  24.  * The offset is an optional argument that specifies the offset where the iteration starts.
  25.  * Returns a result from the iterator.
  26.  * @param {Array, Object} list
  27.  * @param {Function} iterator
  28.  * @param {Number} [offset]
  29.  * @return {Object}
  30.  */
  31. function iterate(list, iterator, offset) {
  32.         for (var i = any(offset, 0), length = list.length; i < length; i++) {
  33.                 iterator(list[i], i);
  34.         }
  35.         return iterator.result;
  36. }
  37.  
  38. function iterateReplace(list, iterator, offset) {
  39.         for (var i = any(offset, 0), length = list.length; i < length; i++) {
  40.                 list[i] = iterator(list[i], i);
  41.         }
  42.         return iterator.result;
  43. }
  44.  
  45. /**
  46.  * For each property of the object invokes the iterator with two arguments:
  47.  * a value of the property and a key of the property.
  48.  * Returns a result from the iterator.
  49.  * @param {Object} object
  50.  * @param {Function} iterator
  51.  * @return {Object}
  52.  */
  53. function enumerate(object, iterator) {
  54.         for (var key in object) {
  55.                 iterator(object[key], key);
  56.         }
  57.         return iterator.result;
  58. }
  59.  
  60. function enumerateReplace(list, iterator, offset) {
  61.         for (var i = any(offset, 0), length = list.length; i < length; i++) {
  62.                 list[i] = iterator(list[i], i);
  63.         }
  64.         return iterator.result;
  65. }
  66.  
  67. /**
  68.  * According the type of the source invokes specific iteration routine:
  69.  * for Enumerables calls its method each(),
  70.  * for array like objects invokes iterate(),
  71.  * for numbers times(), and for other objects enumerate().
  72.  * Returns a result of the used function.
  73.  * @param {Enumerable, Array, Number, Object} source
  74.  * @param {Function} iterator
  75.  * @return {Object}
  76.  */
  77. function each(source, iterator) {
  78.         if (!exists(source)) {
  79.                 return iterator.result;
  80.         }
  81.         if (source.Enumerable) {
  82.                 return source.each(iterator);
  83.         }
  84.         if (isArray(source) || isNumber(source.length)) {
  85.                 return iterate(source, iterator);
  86.         }
  87.         if (isNumber(source)) {
  88.                 return times(source, iterator);
  89.         }
  90.         return enumerate(source, iterator);
  91. }
  92.  
  93. function builder(construct, build) {
  94.         var result = construct();
  95.         var iterator = function(value, key) {
  96.                 build(result, key, value);
  97.         };
  98.         iterator.result = result;
  99.         return iterator;
  100. }
  101.  
  102. /**
  103.  * Returns an iterator that stacks items to an array
  104.  * and sets the array as the result of the iterator.
  105.  * If a template is provided,
  106.  * it first applies the template to these items.
  107.  * @param {Function} [template]
  108.  * @return {Function}
  109.  */
  110. function stacker(template) {
  111.         var result = [];
  112.         var iterator;
  113.         if (exists(template)) {
  114.                 iterator = function(value, key) {
  115.                         result.push(template(value, key));
  116.                 };
  117.         } else {
  118.                 iterator = function(value) {
  119.                         result.push(value);
  120.                 };
  121.         }
  122.         iterator.result = result;
  123.         return iterator;
  124. }
  125.  
  126. /**
  127.  * Returns an iterator that adds items to an object
  128.  * and sets the object as the result of the iterator.
  129.  * If a template is provided,
  130.  * it first applies the template to these items.
  131.  * @param {Function} [template]
  132.  * @return {Function}
  133.  */
  134. function mapper(template) {
  135.         var result = {};
  136.         var iterator;
  137.         if (exists(template)) {
  138.                 iterator = function(value, key) {
  139.                         result[key] = template(value, key);
  140.                 };
  141.         } else {
  142.                 iterator = function(value, key) {
  143.                         result[key] = value;
  144.                 };
  145.         }
  146.         iterator.result = result;
  147.         return iterator;
  148. }
  149.  
  150. function writer(template) {
  151.         var iterator;
  152.         if (exists(template)) {
  153.                 iterator = function(value, key) {
  154.                         iterator.result += template(value, key);
  155.                 };
  156.         } else {
  157.                 iterator = function(value, key) {
  158.                         iterator.result += value;
  159.                 };
  160.         }
  161.         iterator.result = "";
  162.         return iterator;
  163. }
  164.  
  165. /**
  166.  * Returns an iterator
  167.  * that invokes the action also for items of nested arrays
  168.  * and sets a result from the action as the result of the iterator
  169.  * @param {Function} action
  170.  * @return {Function}
  171.  */
  172. function linearizing(action) {
  173.         function iterator(item) {
  174.                 if (isArray(item)) {
  175.                         iterate(item, iterator);
  176.                 } else {
  177.                         action(item);
  178.                 }
  179.         }
  180.         iterator.result = action.result;
  181.         return iterator;
  182. }
  183.  
  184. function where(match, action) {
  185.         function iterator(item, key) {
  186.                 if (match(item, key)) {
  187.                         action(item);
  188.                 }
  189.         }
  190.         iterator.result = action.result;
  191.         return iterator;
  192. }
  193.  
  194. /**
  195.  * Returns an iterator
  196.  * that invokes the action only for existing items
  197.  * and sets a result from the action as the result of the iterator
  198.  * @param {Function} action
  199.  * @return {Function}
  200.  */
  201. function existing(action) {
  202.    return where(exists, action);
  203. }
  204.  
  205. /**
  206.  * Returns an iterator that applies the template on each item
  207.  * and invokes the action on outputs from the template.
  208.  * It sets a result from the action as the result of the iterator
  209.  * @param {Function} action
  210.  * @param {Function} template
  211.  * @return {Function}
  212.  */
  213. function processing(action, template) {
  214.         function iterator(value, key) {
  215.                 action(template(value, key));
  216.         }
  217.         iterator.result = action.result;
  218.         return iterator;
  219. }
  220.  
  221. function keyGetter(value, key) {
  222.         return key;
  223. }
  224.  
  225. /**
  226.  * Specifies that item was found.
  227.  */
  228. var $found = {type: "Found"};
  229.  
  230. /**
  231.  * Returns an index of the first match. If no item matches returns null.
  232.  * @param {Object} items
  233.  * @param {Function} match
  234.  * @return {Number}
  235.  */
  236. function indexOf(items, match) {
  237.         var index = 0;
  238.         try {
  239.                 each(items, function(value, key) {
  240.                         if (match(value, key)) {
  241.                                 throw $found;
  242.                         }
  243.                         index++;
  244.                 });
  245.                 return null;
  246.         } catch (e) {
  247.                 if (e === $found) {
  248.                         return index;
  249.                 }
  250.                 throw e;
  251.         }
  252. }
  253.  
  254. /**
  255.  * Returns the value and the key of the first matched item.
  256.  * @param {Object} items
  257.  * @param {Object} match
  258.  * @return {Array}
  259.  */
  260. function search(items, match) {
  261.         var result;
  262.         try {
  263.                 each(items, function(value, key) {
  264.                         if (match(value, key)) {
  265.                                 result = [value, key];
  266.                                 throw $found;
  267.                         }
  268.                 });
  269.                 return null;
  270.         } catch (e) {
  271.                 if (e === $found) {
  272.                         return result;
  273.                 }
  274.                 throw e;
  275.         }
  276. }
  277.  
  278. function lookup(items, match) {
  279.         var result;
  280.         try {
  281.                 each(items, function(value, key) {
  282.                         result = match(value, key);
  283.                         if (exists(result)) {
  284.                                 throw $found;
  285.                         }
  286.                 });
  287.                 return null;
  288.         } catch (e) {
  289.                 if (e === $found) {
  290.                         return result;
  291.                 }
  292.                 throw e;
  293.         }
  294. }
  295.  
  296.  
  297. /**
  298.  * Returns template that return true if an input object (or its property with the given key) is equal to the value.
  299.  * @param {Object} value
  300.  * @param {String} [key]
  301.  * @param {Function}
  302.  */
  303. function match(value, key) {
  304.         if (exists(key)) {
  305.                 return function(object) {
  306.                         return object[key] === value;
  307.                 };
  308.         } else {
  309.                 return function(object) {
  310.                         return object === value;
  311.                 };
  312.         }
  313. }
  314.  
  315. /**
  316.  * Returns template that return true if a value from a getter of an input object (or its property with the given key) is equal to the value.
  317.  * @param {Object} value
  318.  * @param {String} [key]
  319.  * @param {Function}
  320.  */
  321. function matchGet(value, key) {
  322.         if (exists(key)) {
  323.                 return function(object) {
  324.                         return object[key].get() === value;
  325.                 };
  326.         } else {
  327.                 return function(object) {
  328.                         return object.get() === value;
  329.                 };
  330.         }
  331. }

Raw Paste


Login or Register to edit or fork this paste. It's free.