iter.js 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284
  1. // Copyright 2007 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Python style iteration utilities.
  16. * @author arv@google.com (Erik Arvidsson)
  17. */
  18. goog.provide('goog.iter');
  19. goog.provide('goog.iter.Iterable');
  20. goog.provide('goog.iter.Iterator');
  21. goog.provide('goog.iter.StopIteration');
  22. goog.require('goog.array');
  23. goog.require('goog.asserts');
  24. goog.require('goog.functions');
  25. goog.require('goog.math');
  26. /**
  27. * @typedef {goog.iter.Iterator|{length:number}|{__iterator__}}
  28. */
  29. goog.iter.Iterable;
  30. /**
  31. * Singleton Error object that is used to terminate iterations.
  32. * @const {!Error}
  33. */
  34. goog.iter.StopIteration = ('StopIteration' in goog.global) ?
  35. // For script engines that support legacy iterators.
  36. goog.global['StopIteration'] :
  37. {message: 'StopIteration', stack: ''};
  38. /**
  39. * Class/interface for iterators. An iterator needs to implement a {@code next}
  40. * method and it needs to throw a {@code goog.iter.StopIteration} when the
  41. * iteration passes beyond the end. Iterators have no {@code hasNext} method.
  42. * It is recommended to always use the helper functions to iterate over the
  43. * iterator or in case you are only targeting JavaScript 1.7 for in loops.
  44. * @constructor
  45. * @template VALUE
  46. */
  47. goog.iter.Iterator = function() {};
  48. /**
  49. * Returns the next value of the iteration. This will throw the object
  50. * {@see goog.iter#StopIteration} when the iteration passes the end.
  51. * @return {VALUE} Any object or value.
  52. */
  53. goog.iter.Iterator.prototype.next = function() {
  54. throw goog.iter.StopIteration;
  55. };
  56. /**
  57. * Returns the {@code Iterator} object itself. This is used to implement
  58. * the iterator protocol in JavaScript 1.7
  59. * @param {boolean=} opt_keys Whether to return the keys or values. Default is
  60. * to only return the values. This is being used by the for-in loop (true)
  61. * and the for-each-in loop (false). Even though the param gives a hint
  62. * about what the iterator will return there is no guarantee that it will
  63. * return the keys when true is passed.
  64. * @return {!goog.iter.Iterator<VALUE>} The object itself.
  65. */
  66. goog.iter.Iterator.prototype.__iterator__ = function(opt_keys) {
  67. return this;
  68. };
  69. /**
  70. * Returns an iterator that knows how to iterate over the values in the object.
  71. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable If the
  72. * object is an iterator it will be returned as is. If the object has an
  73. * {@code __iterator__} method that will be called to get the value
  74. * iterator. If the object is an array-like object we create an iterator
  75. * for that.
  76. * @return {!goog.iter.Iterator<VALUE>} An iterator that knows how to iterate
  77. * over the values in {@code iterable}.
  78. * @template VALUE
  79. */
  80. goog.iter.toIterator = function(iterable) {
  81. if (iterable instanceof goog.iter.Iterator) {
  82. return iterable;
  83. }
  84. if (typeof iterable.__iterator__ == 'function') {
  85. return iterable.__iterator__(false);
  86. }
  87. if (goog.isArrayLike(iterable)) {
  88. var i = 0;
  89. var newIter = new goog.iter.Iterator;
  90. newIter.next = function() {
  91. while (true) {
  92. if (i >= iterable.length) {
  93. throw goog.iter.StopIteration;
  94. }
  95. // Don't include deleted elements.
  96. if (!(i in iterable)) {
  97. i++;
  98. continue;
  99. }
  100. return iterable[i++];
  101. }
  102. };
  103. return newIter;
  104. }
  105. // TODO(arv): Should we fall back on goog.structs.getValues()?
  106. throw Error('Not implemented');
  107. };
  108. /**
  109. * Calls a function for each element in the iterator with the element of the
  110. * iterator passed as argument.
  111. *
  112. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
  113. * to iterate over. If the iterable is an object {@code toIterator} will be
  114. * called on it.
  115. * @param {function(this:THIS,VALUE,?,!goog.iter.Iterator<VALUE>)} f
  116. * The function to call for every element. This function takes 3 arguments
  117. * (the element, undefined, and the iterator) and the return value is
  118. * irrelevant. The reason for passing undefined as the second argument is
  119. * so that the same function can be used in {@see goog.array#forEach} as
  120. * well as others. The third parameter is of type "number" for
  121. * arraylike objects, undefined, otherwise.
  122. * @param {THIS=} opt_obj The object to be used as the value of 'this' within
  123. * {@code f}.
  124. * @template THIS, VALUE
  125. */
  126. goog.iter.forEach = function(iterable, f, opt_obj) {
  127. if (goog.isArrayLike(iterable)) {
  128. try {
  129. // NOTES: this passes the index number to the second parameter
  130. // of the callback contrary to the documentation above.
  131. goog.array.forEach(
  132. /** @type {IArrayLike<?>} */ (iterable), f, opt_obj);
  133. } catch (ex) {
  134. if (ex !== goog.iter.StopIteration) {
  135. throw ex;
  136. }
  137. }
  138. } else {
  139. iterable = goog.iter.toIterator(iterable);
  140. try {
  141. while (true) {
  142. f.call(opt_obj, iterable.next(), undefined, iterable);
  143. }
  144. } catch (ex) {
  145. if (ex !== goog.iter.StopIteration) {
  146. throw ex;
  147. }
  148. }
  149. }
  150. };
  151. /**
  152. * Calls a function for every element in the iterator, and if the function
  153. * returns true adds the element to a new iterator.
  154. *
  155. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
  156. * to iterate over.
  157. * @param {
  158. * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
  159. * The function to call for every element. This function takes 3 arguments
  160. * (the element, undefined, and the iterator) and should return a boolean.
  161. * If the return value is true the element will be included in the returned
  162. * iterator. If it is false the element is not included.
  163. * @param {THIS=} opt_obj The object to be used as the value of 'this' within
  164. * {@code f}.
  165. * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements
  166. * that passed the test are present.
  167. * @template THIS, VALUE
  168. */
  169. goog.iter.filter = function(iterable, f, opt_obj) {
  170. var iterator = goog.iter.toIterator(iterable);
  171. var newIter = new goog.iter.Iterator;
  172. newIter.next = function() {
  173. while (true) {
  174. var val = iterator.next();
  175. if (f.call(opt_obj, val, undefined, iterator)) {
  176. return val;
  177. }
  178. }
  179. };
  180. return newIter;
  181. };
  182. /**
  183. * Calls a function for every element in the iterator, and if the function
  184. * returns false adds the element to a new iterator.
  185. *
  186. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
  187. * to iterate over.
  188. * @param {
  189. * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
  190. * The function to call for every element. This function takes 3 arguments
  191. * (the element, undefined, and the iterator) and should return a boolean.
  192. * If the return value is false the element will be included in the returned
  193. * iterator. If it is true the element is not included.
  194. * @param {THIS=} opt_obj The object to be used as the value of 'this' within
  195. * {@code f}.
  196. * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements
  197. * that did not pass the test are present.
  198. * @template THIS, VALUE
  199. */
  200. goog.iter.filterFalse = function(iterable, f, opt_obj) {
  201. return goog.iter.filter(iterable, goog.functions.not(f), opt_obj);
  202. };
  203. /**
  204. * Creates a new iterator that returns the values in a range. This function
  205. * can take 1, 2 or 3 arguments:
  206. * <pre>
  207. * range(5) same as range(0, 5, 1)
  208. * range(2, 5) same as range(2, 5, 1)
  209. * </pre>
  210. *
  211. * @param {number} startOrStop The stop value if only one argument is provided.
  212. * The start value if 2 or more arguments are provided. If only one
  213. * argument is used the start value is 0.
  214. * @param {number=} opt_stop The stop value. If left out then the first
  215. * argument is used as the stop value.
  216. * @param {number=} opt_step The number to increment with between each call to
  217. * next. This can be negative.
  218. * @return {!goog.iter.Iterator<number>} A new iterator that returns the values
  219. * in the range.
  220. */
  221. goog.iter.range = function(startOrStop, opt_stop, opt_step) {
  222. var start = 0;
  223. var stop = startOrStop;
  224. var step = opt_step || 1;
  225. if (arguments.length > 1) {
  226. start = startOrStop;
  227. stop = opt_stop;
  228. }
  229. if (step == 0) {
  230. throw Error('Range step argument must not be zero');
  231. }
  232. var newIter = new goog.iter.Iterator;
  233. newIter.next = function() {
  234. if (step > 0 && start >= stop || step < 0 && start <= stop) {
  235. throw goog.iter.StopIteration;
  236. }
  237. var rv = start;
  238. start += step;
  239. return rv;
  240. };
  241. return newIter;
  242. };
  243. /**
  244. * Joins the values in a iterator with a delimiter.
  245. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
  246. * to get the values from.
  247. * @param {string} deliminator The text to put between the values.
  248. * @return {string} The joined value string.
  249. * @template VALUE
  250. */
  251. goog.iter.join = function(iterable, deliminator) {
  252. return goog.iter.toArray(iterable).join(deliminator);
  253. };
  254. /**
  255. * For every element in the iterator call a function and return a new iterator
  256. * with that value.
  257. *
  258. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  259. * iterator to iterate over.
  260. * @param {
  261. * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):RESULT} f
  262. * The function to call for every element. This function takes 3 arguments
  263. * (the element, undefined, and the iterator) and should return a new value.
  264. * @param {THIS=} opt_obj The object to be used as the value of 'this' within
  265. * {@code f}.
  266. * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the
  267. * results of applying the function to each element in the original
  268. * iterator.
  269. * @template THIS, VALUE, RESULT
  270. */
  271. goog.iter.map = function(iterable, f, opt_obj) {
  272. var iterator = goog.iter.toIterator(iterable);
  273. var newIter = new goog.iter.Iterator;
  274. newIter.next = function() {
  275. var val = iterator.next();
  276. return f.call(opt_obj, val, undefined, iterator);
  277. };
  278. return newIter;
  279. };
  280. /**
  281. * Passes every element of an iterator into a function and accumulates the
  282. * result.
  283. *
  284. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
  285. * to iterate over.
  286. * @param {function(this:THIS,VALUE,VALUE):VALUE} f The function to call for
  287. * every element. This function takes 2 arguments (the function's previous
  288. * result or the initial value, and the value of the current element).
  289. * function(previousValue, currentElement) : newValue.
  290. * @param {VALUE} val The initial value to pass into the function on the first
  291. * call.
  292. * @param {THIS=} opt_obj The object to be used as the value of 'this' within
  293. * f.
  294. * @return {VALUE} Result of evaluating f repeatedly across the values of
  295. * the iterator.
  296. * @template THIS, VALUE
  297. */
  298. goog.iter.reduce = function(iterable, f, val, opt_obj) {
  299. var rval = val;
  300. goog.iter.forEach(
  301. iterable, function(val) { rval = f.call(opt_obj, rval, val); });
  302. return rval;
  303. };
  304. /**
  305. * Goes through the values in the iterator. Calls f for each of these, and if
  306. * any of them returns true, this returns true (without checking the rest). If
  307. * all return false this will return false.
  308. *
  309. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
  310. * object.
  311. * @param {
  312. * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
  313. * The function to call for every value. This function takes 3 arguments
  314. * (the value, undefined, and the iterator) and should return a boolean.
  315. * @param {THIS=} opt_obj The object to be used as the value of 'this' within
  316. * {@code f}.
  317. * @return {boolean} true if any value passes the test.
  318. * @template THIS, VALUE
  319. */
  320. goog.iter.some = function(iterable, f, opt_obj) {
  321. iterable = goog.iter.toIterator(iterable);
  322. try {
  323. while (true) {
  324. if (f.call(opt_obj, iterable.next(), undefined, iterable)) {
  325. return true;
  326. }
  327. }
  328. } catch (ex) {
  329. if (ex !== goog.iter.StopIteration) {
  330. throw ex;
  331. }
  332. }
  333. return false;
  334. };
  335. /**
  336. * Goes through the values in the iterator. Calls f for each of these and if any
  337. * of them returns false this returns false (without checking the rest). If all
  338. * return true this will return true.
  339. *
  340. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
  341. * object.
  342. * @param {
  343. * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
  344. * The function to call for every value. This function takes 3 arguments
  345. * (the value, undefined, and the iterator) and should return a boolean.
  346. * @param {THIS=} opt_obj The object to be used as the value of 'this' within
  347. * {@code f}.
  348. * @return {boolean} true if every value passes the test.
  349. * @template THIS, VALUE
  350. */
  351. goog.iter.every = function(iterable, f, opt_obj) {
  352. iterable = goog.iter.toIterator(iterable);
  353. try {
  354. while (true) {
  355. if (!f.call(opt_obj, iterable.next(), undefined, iterable)) {
  356. return false;
  357. }
  358. }
  359. } catch (ex) {
  360. if (ex !== goog.iter.StopIteration) {
  361. throw ex;
  362. }
  363. }
  364. return true;
  365. };
  366. /**
  367. * Takes zero or more iterables and returns one iterator that will iterate over
  368. * them in the order chained.
  369. * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
  370. * number of iterable objects.
  371. * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will
  372. * iterate over all the given iterables' contents.
  373. * @template VALUE
  374. */
  375. goog.iter.chain = function(var_args) {
  376. return goog.iter.chainFromIterable(arguments);
  377. };
  378. /**
  379. * Takes a single iterable containing zero or more iterables and returns one
  380. * iterator that will iterate over each one in the order given.
  381. * @see https://goo.gl/5NRp5d
  382. * @param {goog.iter.Iterable} iterable The iterable of iterables to chain.
  383. * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will
  384. * iterate over all the contents of the iterables contained within
  385. * {@code iterable}.
  386. * @template VALUE
  387. */
  388. goog.iter.chainFromIterable = function(iterable) {
  389. var iterator = goog.iter.toIterator(iterable);
  390. var iter = new goog.iter.Iterator();
  391. var current = null;
  392. iter.next = function() {
  393. while (true) {
  394. if (current == null) {
  395. var it = iterator.next();
  396. current = goog.iter.toIterator(it);
  397. }
  398. try {
  399. return current.next();
  400. } catch (ex) {
  401. if (ex !== goog.iter.StopIteration) {
  402. throw ex;
  403. }
  404. current = null;
  405. }
  406. }
  407. };
  408. return iter;
  409. };
  410. /**
  411. * Builds a new iterator that iterates over the original, but skips elements as
  412. * long as a supplied function returns true.
  413. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
  414. * object.
  415. * @param {
  416. * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
  417. * The function to call for every value. This function takes 3 arguments
  418. * (the value, undefined, and the iterator) and should return a boolean.
  419. * @param {THIS=} opt_obj The object to be used as the value of 'this' within
  420. * {@code f}.
  421. * @return {!goog.iter.Iterator<VALUE>} A new iterator that drops elements from
  422. * the original iterator as long as {@code f} is true.
  423. * @template THIS, VALUE
  424. */
  425. goog.iter.dropWhile = function(iterable, f, opt_obj) {
  426. var iterator = goog.iter.toIterator(iterable);
  427. var newIter = new goog.iter.Iterator;
  428. var dropping = true;
  429. newIter.next = function() {
  430. while (true) {
  431. var val = iterator.next();
  432. if (dropping && f.call(opt_obj, val, undefined, iterator)) {
  433. continue;
  434. } else {
  435. dropping = false;
  436. }
  437. return val;
  438. }
  439. };
  440. return newIter;
  441. };
  442. /**
  443. * Builds a new iterator that iterates over the original, but only as long as a
  444. * supplied function returns true.
  445. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
  446. * object.
  447. * @param {
  448. * function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
  449. * The function to call for every value. This function takes 3 arguments
  450. * (the value, undefined, and the iterator) and should return a boolean.
  451. * @param {THIS=} opt_obj This is used as the 'this' object in f when called.
  452. * @return {!goog.iter.Iterator<VALUE>} A new iterator that keeps elements in
  453. * the original iterator as long as the function is true.
  454. * @template THIS, VALUE
  455. */
  456. goog.iter.takeWhile = function(iterable, f, opt_obj) {
  457. var iterator = goog.iter.toIterator(iterable);
  458. var iter = new goog.iter.Iterator();
  459. iter.next = function() {
  460. var val = iterator.next();
  461. if (f.call(opt_obj, val, undefined, iterator)) {
  462. return val;
  463. }
  464. throw goog.iter.StopIteration;
  465. };
  466. return iter;
  467. };
  468. /**
  469. * Converts the iterator to an array
  470. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
  471. * to convert to an array.
  472. * @return {!Array<VALUE>} An array of the elements the iterator iterates over.
  473. * @template VALUE
  474. */
  475. goog.iter.toArray = function(iterable) {
  476. // Fast path for array-like.
  477. if (goog.isArrayLike(iterable)) {
  478. return goog.array.toArray(/** @type {!IArrayLike<?>} */ (iterable));
  479. }
  480. iterable = goog.iter.toIterator(iterable);
  481. var array = [];
  482. goog.iter.forEach(iterable, function(val) { array.push(val); });
  483. return array;
  484. };
  485. /**
  486. * Iterates over two iterables and returns true if they contain the same
  487. * sequence of elements and have the same length.
  488. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable1 The first
  489. * iterable object.
  490. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable2 The second
  491. * iterable object.
  492. * @param {function(VALUE,VALUE):boolean=} opt_equalsFn Optional comparison
  493. * function.
  494. * Should take two arguments to compare, and return true if the arguments
  495. * are equal. Defaults to {@link goog.array.defaultCompareEquality} which
  496. * compares the elements using the built-in '===' operator.
  497. * @return {boolean} true if the iterables contain the same sequence of elements
  498. * and have the same length.
  499. * @template VALUE
  500. */
  501. goog.iter.equals = function(iterable1, iterable2, opt_equalsFn) {
  502. var fillValue = {};
  503. var pairs = goog.iter.zipLongest(fillValue, iterable1, iterable2);
  504. var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;
  505. return goog.iter.every(
  506. pairs, function(pair) { return equalsFn(pair[0], pair[1]); });
  507. };
  508. /**
  509. * Advances the iterator to the next position, returning the given default value
  510. * instead of throwing an exception if the iterator has no more entries.
  511. * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterable
  512. * object.
  513. * @param {VALUE} defaultValue The value to return if the iterator is empty.
  514. * @return {VALUE} The next item in the iteration, or defaultValue if the
  515. * iterator was empty.
  516. * @template VALUE
  517. */
  518. goog.iter.nextOrValue = function(iterable, defaultValue) {
  519. try {
  520. return goog.iter.toIterator(iterable).next();
  521. } catch (e) {
  522. if (e != goog.iter.StopIteration) {
  523. throw e;
  524. }
  525. return defaultValue;
  526. }
  527. };
  528. /**
  529. * Cartesian product of zero or more sets. Gives an iterator that gives every
  530. * combination of one element chosen from each set. For example,
  531. * ([1, 2], [3, 4]) gives ([1, 3], [1, 4], [2, 3], [2, 4]).
  532. * @see http://docs.python.org/library/itertools.html#itertools.product
  533. * @param {...!IArrayLike<VALUE>} var_args Zero or more sets, as
  534. * arrays.
  535. * @return {!goog.iter.Iterator<!Array<VALUE>>} An iterator that gives each
  536. * n-tuple (as an array).
  537. * @template VALUE
  538. */
  539. goog.iter.product = function(var_args) {
  540. var someArrayEmpty =
  541. goog.array.some(arguments, function(arr) { return !arr.length; });
  542. // An empty set in a cartesian product gives an empty set.
  543. if (someArrayEmpty || !arguments.length) {
  544. return new goog.iter.Iterator();
  545. }
  546. var iter = new goog.iter.Iterator();
  547. var arrays = arguments;
  548. // The first indices are [0, 0, ...]
  549. var indicies = goog.array.repeat(0, arrays.length);
  550. iter.next = function() {
  551. if (indicies) {
  552. var retVal = goog.array.map(indicies, function(valueIndex, arrayIndex) {
  553. return arrays[arrayIndex][valueIndex];
  554. });
  555. // Generate the next-largest indices for the next call.
  556. // Increase the rightmost index. If it goes over, increase the next
  557. // rightmost (like carry-over addition).
  558. for (var i = indicies.length - 1; i >= 0; i--) {
  559. // Assertion prevents compiler warning below.
  560. goog.asserts.assert(indicies);
  561. if (indicies[i] < arrays[i].length - 1) {
  562. indicies[i]++;
  563. break;
  564. }
  565. // We're at the last indices (the last element of every array), so
  566. // the iteration is over on the next call.
  567. if (i == 0) {
  568. indicies = null;
  569. break;
  570. }
  571. // Reset the index in this column and loop back to increment the
  572. // next one.
  573. indicies[i] = 0;
  574. }
  575. return retVal;
  576. }
  577. throw goog.iter.StopIteration;
  578. };
  579. return iter;
  580. };
  581. /**
  582. * Create an iterator to cycle over the iterable's elements indefinitely.
  583. * For example, ([1, 2, 3]) would return : 1, 2, 3, 1, 2, 3, ...
  584. * @see: http://docs.python.org/library/itertools.html#itertools.cycle.
  585. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  586. * iterable object.
  587. * @return {!goog.iter.Iterator<VALUE>} An iterator that iterates indefinitely
  588. * over the values in {@code iterable}.
  589. * @template VALUE
  590. */
  591. goog.iter.cycle = function(iterable) {
  592. var baseIterator = goog.iter.toIterator(iterable);
  593. // We maintain a cache to store the iterable elements as we iterate
  594. // over them. The cache is used to return elements once we have
  595. // iterated over the iterable once.
  596. var cache = [];
  597. var cacheIndex = 0;
  598. var iter = new goog.iter.Iterator();
  599. // This flag is set after the iterable is iterated over once
  600. var useCache = false;
  601. iter.next = function() {
  602. var returnElement = null;
  603. // Pull elements off the original iterator if not using cache
  604. if (!useCache) {
  605. try {
  606. // Return the element from the iterable
  607. returnElement = baseIterator.next();
  608. cache.push(returnElement);
  609. return returnElement;
  610. } catch (e) {
  611. // If an exception other than StopIteration is thrown
  612. // or if there are no elements to iterate over (the iterable was empty)
  613. // throw an exception
  614. if (e != goog.iter.StopIteration || goog.array.isEmpty(cache)) {
  615. throw e;
  616. }
  617. // set useCache to true after we know that a 'StopIteration' exception
  618. // was thrown and the cache is not empty (to handle the 'empty iterable'
  619. // use case)
  620. useCache = true;
  621. }
  622. }
  623. returnElement = cache[cacheIndex];
  624. cacheIndex = (cacheIndex + 1) % cache.length;
  625. return returnElement;
  626. };
  627. return iter;
  628. };
  629. /**
  630. * Creates an iterator that counts indefinitely from a starting value.
  631. * @see http://docs.python.org/2/library/itertools.html#itertools.count
  632. * @param {number=} opt_start The starting value. Default is 0.
  633. * @param {number=} opt_step The number to increment with between each call to
  634. * next. Negative and floating point numbers are allowed. Default is 1.
  635. * @return {!goog.iter.Iterator<number>} A new iterator that returns the values
  636. * in the series.
  637. */
  638. goog.iter.count = function(opt_start, opt_step) {
  639. var counter = opt_start || 0;
  640. var step = goog.isDef(opt_step) ? opt_step : 1;
  641. var iter = new goog.iter.Iterator();
  642. iter.next = function() {
  643. var returnValue = counter;
  644. counter += step;
  645. return returnValue;
  646. };
  647. return iter;
  648. };
  649. /**
  650. * Creates an iterator that returns the same object or value repeatedly.
  651. * @param {VALUE} value Any object or value to repeat.
  652. * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the
  653. * repeated value.
  654. * @template VALUE
  655. */
  656. goog.iter.repeat = function(value) {
  657. var iter = new goog.iter.Iterator();
  658. iter.next = goog.functions.constant(value);
  659. return iter;
  660. };
  661. /**
  662. * Creates an iterator that returns running totals from the numbers in
  663. * {@code iterable}. For example, the array {@code [1, 2, 3, 4, 5]} yields
  664. * {@code 1 -> 3 -> 6 -> 10 -> 15}.
  665. * @see http://docs.python.org/3.2/library/itertools.html#itertools.accumulate
  666. * @param {!goog.iter.Iterable} iterable The iterable of numbers to
  667. * accumulate.
  668. * @return {!goog.iter.Iterator<number>} A new iterator that returns the
  669. * numbers in the series.
  670. */
  671. goog.iter.accumulate = function(iterable) {
  672. var iterator = goog.iter.toIterator(iterable);
  673. var total = 0;
  674. var iter = new goog.iter.Iterator();
  675. iter.next = function() {
  676. total += iterator.next();
  677. return total;
  678. };
  679. return iter;
  680. };
  681. /**
  682. * Creates an iterator that returns arrays containing the ith elements from the
  683. * provided iterables. The returned arrays will be the same size as the number
  684. * of iterables given in {@code var_args}. Once the shortest iterable is
  685. * exhausted, subsequent calls to {@code next()} will throw
  686. * {@code goog.iter.StopIteration}.
  687. * @see http://docs.python.org/2/library/itertools.html#itertools.izip
  688. * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
  689. * number of iterable objects.
  690. * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns
  691. * arrays of elements from the provided iterables.
  692. * @template VALUE
  693. */
  694. goog.iter.zip = function(var_args) {
  695. var args = arguments;
  696. var iter = new goog.iter.Iterator();
  697. if (args.length > 0) {
  698. var iterators = goog.array.map(args, goog.iter.toIterator);
  699. iter.next = function() {
  700. var arr = goog.array.map(iterators, function(it) { return it.next(); });
  701. return arr;
  702. };
  703. }
  704. return iter;
  705. };
  706. /**
  707. * Creates an iterator that returns arrays containing the ith elements from the
  708. * provided iterables. The returned arrays will be the same size as the number
  709. * of iterables given in {@code var_args}. Shorter iterables will be extended
  710. * with {@code fillValue}. Once the longest iterable is exhausted, subsequent
  711. * calls to {@code next()} will throw {@code goog.iter.StopIteration}.
  712. * @see http://docs.python.org/2/library/itertools.html#itertools.izip_longest
  713. * @param {VALUE} fillValue The object or value used to fill shorter iterables.
  714. * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
  715. * number of iterable objects.
  716. * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns
  717. * arrays of elements from the provided iterables.
  718. * @template VALUE
  719. */
  720. goog.iter.zipLongest = function(fillValue, var_args) {
  721. var args = goog.array.slice(arguments, 1);
  722. var iter = new goog.iter.Iterator();
  723. if (args.length > 0) {
  724. var iterators = goog.array.map(args, goog.iter.toIterator);
  725. iter.next = function() {
  726. var iteratorsHaveValues = false; // false when all iterators are empty.
  727. var arr = goog.array.map(iterators, function(it) {
  728. var returnValue;
  729. try {
  730. returnValue = it.next();
  731. // Iterator had a value, so we've not exhausted the iterators.
  732. // Set flag accordingly.
  733. iteratorsHaveValues = true;
  734. } catch (ex) {
  735. if (ex !== goog.iter.StopIteration) {
  736. throw ex;
  737. }
  738. returnValue = fillValue;
  739. }
  740. return returnValue;
  741. });
  742. if (!iteratorsHaveValues) {
  743. throw goog.iter.StopIteration;
  744. }
  745. return arr;
  746. };
  747. }
  748. return iter;
  749. };
  750. /**
  751. * Creates an iterator that filters {@code iterable} based on a series of
  752. * {@code selectors}. On each call to {@code next()}, one item is taken from
  753. * both the {@code iterable} and {@code selectors} iterators. If the item from
  754. * {@code selectors} evaluates to true, the item from {@code iterable} is given.
  755. * Otherwise, it is skipped. Once either {@code iterable} or {@code selectors}
  756. * is exhausted, subsequent calls to {@code next()} will throw
  757. * {@code goog.iter.StopIteration}.
  758. * @see http://docs.python.org/2/library/itertools.html#itertools.compress
  759. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  760. * iterable to filter.
  761. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} selectors An
  762. * iterable of items to be evaluated in a boolean context to determine if
  763. * the corresponding element in {@code iterable} should be included in the
  764. * result.
  765. * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the
  766. * filtered values.
  767. * @template VALUE
  768. */
  769. goog.iter.compress = function(iterable, selectors) {
  770. var selectorIterator = goog.iter.toIterator(selectors);
  771. return goog.iter.filter(
  772. iterable, function() { return !!selectorIterator.next(); });
  773. };
  774. /**
  775. * Implements the {@code goog.iter.groupBy} iterator.
  776. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  777. * iterable to group.
  778. * @param {function(VALUE): KEY=} opt_keyFunc Optional function for
  779. * determining the key value for each group in the {@code iterable}. Default
  780. * is the identity function.
  781. * @constructor
  782. * @extends {goog.iter.Iterator<!Array<?>>}
  783. * @template KEY, VALUE
  784. * @private
  785. */
  786. goog.iter.GroupByIterator_ = function(iterable, opt_keyFunc) {
  787. /**
  788. * The iterable to group, coerced to an iterator.
  789. * @type {!goog.iter.Iterator}
  790. */
  791. this.iterator = goog.iter.toIterator(iterable);
  792. /**
  793. * A function for determining the key value for each element in the iterable.
  794. * If no function is provided, the identity function is used and returns the
  795. * element unchanged.
  796. * @type {function(VALUE): KEY}
  797. */
  798. this.keyFunc = opt_keyFunc || goog.functions.identity;
  799. /**
  800. * The target key for determining the start of a group.
  801. * @type {KEY}
  802. */
  803. this.targetKey;
  804. /**
  805. * The current key visited during iteration.
  806. * @type {KEY}
  807. */
  808. this.currentKey;
  809. /**
  810. * The current value being added to the group.
  811. * @type {VALUE}
  812. */
  813. this.currentValue;
  814. };
  815. goog.inherits(goog.iter.GroupByIterator_, goog.iter.Iterator);
  816. /** @override */
  817. goog.iter.GroupByIterator_.prototype.next = function() {
  818. while (this.currentKey == this.targetKey) {
  819. this.currentValue = this.iterator.next(); // Exits on StopIteration
  820. this.currentKey = this.keyFunc(this.currentValue);
  821. }
  822. this.targetKey = this.currentKey;
  823. return [this.currentKey, this.groupItems_(this.targetKey)];
  824. };
  825. /**
  826. * Performs the grouping of objects using the given key.
  827. * @param {KEY} targetKey The target key object for the group.
  828. * @return {!Array<VALUE>} An array of grouped objects.
  829. * @private
  830. */
  831. goog.iter.GroupByIterator_.prototype.groupItems_ = function(targetKey) {
  832. var arr = [];
  833. while (this.currentKey == targetKey) {
  834. arr.push(this.currentValue);
  835. try {
  836. this.currentValue = this.iterator.next();
  837. } catch (ex) {
  838. if (ex !== goog.iter.StopIteration) {
  839. throw ex;
  840. }
  841. break;
  842. }
  843. this.currentKey = this.keyFunc(this.currentValue);
  844. }
  845. return arr;
  846. };
  847. /**
  848. * Creates an iterator that returns arrays containing elements from the
  849. * {@code iterable} grouped by a key value. For iterables with repeated
  850. * elements (i.e. sorted according to a particular key function), this function
  851. * has a {@code uniq}-like effect. For example, grouping the array:
  852. * {@code [A, B, B, C, C, A]} produces
  853. * {@code [A, [A]], [B, [B, B]], [C, [C, C]], [A, [A]]}.
  854. * @see http://docs.python.org/2/library/itertools.html#itertools.groupby
  855. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  856. * iterable to group.
  857. * @param {function(VALUE): KEY=} opt_keyFunc Optional function for
  858. * determining the key value for each group in the {@code iterable}. Default
  859. * is the identity function.
  860. * @return {!goog.iter.Iterator<!Array<?>>} A new iterator that returns
  861. * arrays of consecutive key and groups.
  862. * @template KEY, VALUE
  863. */
  864. goog.iter.groupBy = function(iterable, opt_keyFunc) {
  865. return new goog.iter.GroupByIterator_(iterable, opt_keyFunc);
  866. };
  867. /**
  868. * Gives an iterator that gives the result of calling the given function
  869. * <code>f</code> with the arguments taken from the next element from
  870. * <code>iterable</code> (the elements are expected to also be iterables).
  871. *
  872. * Similar to {@see goog.iter#map} but allows the function to accept multiple
  873. * arguments from the iterable.
  874. *
  875. * @param {!goog.iter.Iterable} iterable The iterable of
  876. * iterables to iterate over.
  877. * @param {function(this:THIS,...*):RESULT} f The function to call for every
  878. * element. This function takes N+2 arguments, where N represents the
  879. * number of items from the next element of the iterable. The two
  880. * additional arguments passed to the function are undefined and the
  881. * iterator itself. The function should return a new value.
  882. * @param {THIS=} opt_obj The object to be used as the value of 'this' within
  883. * {@code f}.
  884. * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the
  885. * results of applying the function to each element in the original
  886. * iterator.
  887. * @template THIS, RESULT
  888. */
  889. goog.iter.starMap = function(iterable, f, opt_obj) {
  890. var iterator = goog.iter.toIterator(iterable);
  891. var iter = new goog.iter.Iterator();
  892. iter.next = function() {
  893. var args = goog.iter.toArray(iterator.next());
  894. return f.apply(opt_obj, goog.array.concat(args, undefined, iterator));
  895. };
  896. return iter;
  897. };
  898. /**
  899. * Returns an array of iterators each of which can iterate over the values in
  900. * {@code iterable} without advancing the others.
  901. * @see http://docs.python.org/2/library/itertools.html#itertools.tee
  902. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  903. * iterable to tee.
  904. * @param {number=} opt_num The number of iterators to create. Default is 2.
  905. * @return {!Array<goog.iter.Iterator<VALUE>>} An array of iterators.
  906. * @template VALUE
  907. */
  908. goog.iter.tee = function(iterable, opt_num) {
  909. var iterator = goog.iter.toIterator(iterable);
  910. var num = goog.isNumber(opt_num) ? opt_num : 2;
  911. var buffers =
  912. goog.array.map(goog.array.range(num), function() { return []; });
  913. var addNextIteratorValueToBuffers = function() {
  914. var val = iterator.next();
  915. goog.array.forEach(buffers, function(buffer) { buffer.push(val); });
  916. };
  917. var createIterator = function(buffer) {
  918. // Each tee'd iterator has an associated buffer (initially empty). When a
  919. // tee'd iterator's buffer is empty, it calls
  920. // addNextIteratorValueToBuffers(), adding the next value to all tee'd
  921. // iterators' buffers, and then returns that value. This allows each
  922. // iterator to be advanced independently.
  923. var iter = new goog.iter.Iterator();
  924. iter.next = function() {
  925. if (goog.array.isEmpty(buffer)) {
  926. addNextIteratorValueToBuffers();
  927. }
  928. goog.asserts.assert(!goog.array.isEmpty(buffer));
  929. return buffer.shift();
  930. };
  931. return iter;
  932. };
  933. return goog.array.map(buffers, createIterator);
  934. };
  935. /**
  936. * Creates an iterator that returns arrays containing a count and an element
  937. * obtained from the given {@code iterable}.
  938. * @see http://docs.python.org/2/library/functions.html#enumerate
  939. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  940. * iterable to enumerate.
  941. * @param {number=} opt_start Optional starting value. Default is 0.
  942. * @return {!goog.iter.Iterator<!Array<?>>} A new iterator containing
  943. * count/item pairs.
  944. * @template VALUE
  945. */
  946. goog.iter.enumerate = function(iterable, opt_start) {
  947. return goog.iter.zip(goog.iter.count(opt_start), iterable);
  948. };
  949. /**
  950. * Creates an iterator that returns the first {@code limitSize} elements from an
  951. * iterable. If this number is greater than the number of elements in the
  952. * iterable, all the elements are returned.
  953. * @see http://goo.gl/V0sihp Inspired by the limit iterator in Guava.
  954. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  955. * iterable to limit.
  956. * @param {number} limitSize The maximum number of elements to return.
  957. * @return {!goog.iter.Iterator<VALUE>} A new iterator containing
  958. * {@code limitSize} elements.
  959. * @template VALUE
  960. */
  961. goog.iter.limit = function(iterable, limitSize) {
  962. goog.asserts.assert(goog.math.isInt(limitSize) && limitSize >= 0);
  963. var iterator = goog.iter.toIterator(iterable);
  964. var iter = new goog.iter.Iterator();
  965. var remaining = limitSize;
  966. iter.next = function() {
  967. if (remaining-- > 0) {
  968. return iterator.next();
  969. }
  970. throw goog.iter.StopIteration;
  971. };
  972. return iter;
  973. };
  974. /**
  975. * Creates an iterator that is advanced {@code count} steps ahead. Consumed
  976. * values are silently discarded. If {@code count} is greater than the number
  977. * of elements in {@code iterable}, an empty iterator is returned. Subsequent
  978. * calls to {@code next()} will throw {@code goog.iter.StopIteration}.
  979. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  980. * iterable to consume.
  981. * @param {number} count The number of elements to consume from the iterator.
  982. * @return {!goog.iter.Iterator<VALUE>} An iterator advanced zero or more steps
  983. * ahead.
  984. * @template VALUE
  985. */
  986. goog.iter.consume = function(iterable, count) {
  987. goog.asserts.assert(goog.math.isInt(count) && count >= 0);
  988. var iterator = goog.iter.toIterator(iterable);
  989. while (count-- > 0) {
  990. goog.iter.nextOrValue(iterator, null);
  991. }
  992. return iterator;
  993. };
  994. /**
  995. * Creates an iterator that returns a range of elements from an iterable.
  996. * Similar to {@see goog.array#slice} but does not support negative indexes.
  997. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  998. * iterable to slice.
  999. * @param {number} start The index of the first element to return.
  1000. * @param {number=} opt_end The index after the last element to return. If
  1001. * defined, must be greater than or equal to {@code start}.
  1002. * @return {!goog.iter.Iterator<VALUE>} A new iterator containing a slice of
  1003. * the original.
  1004. * @template VALUE
  1005. */
  1006. goog.iter.slice = function(iterable, start, opt_end) {
  1007. goog.asserts.assert(goog.math.isInt(start) && start >= 0);
  1008. var iterator = goog.iter.consume(iterable, start);
  1009. if (goog.isNumber(opt_end)) {
  1010. goog.asserts.assert(goog.math.isInt(opt_end) && opt_end >= start);
  1011. iterator = goog.iter.limit(iterator, opt_end - start /* limitSize */);
  1012. }
  1013. return iterator;
  1014. };
  1015. /**
  1016. * Checks an array for duplicate elements.
  1017. * @param {?IArrayLike<VALUE>} arr The array to check for
  1018. * duplicates.
  1019. * @return {boolean} True, if the array contains duplicates, false otherwise.
  1020. * @private
  1021. * @template VALUE
  1022. */
  1023. // TODO(user): Consider moving this into goog.array as a public function.
  1024. goog.iter.hasDuplicates_ = function(arr) {
  1025. var deduped = [];
  1026. goog.array.removeDuplicates(arr, deduped);
  1027. return arr.length != deduped.length;
  1028. };
  1029. /**
  1030. * Creates an iterator that returns permutations of elements in
  1031. * {@code iterable}.
  1032. *
  1033. * Permutations are obtained by taking the Cartesian product of
  1034. * {@code opt_length} iterables and filtering out those with repeated
  1035. * elements. For example, the permutations of {@code [1,2,3]} are
  1036. * {@code [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]}.
  1037. * @see http://docs.python.org/2/library/itertools.html#itertools.permutations
  1038. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  1039. * iterable from which to generate permutations.
  1040. * @param {number=} opt_length Length of each permutation. If omitted, defaults
  1041. * to the length of {@code iterable}.
  1042. * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing the
  1043. * permutations of {@code iterable}.
  1044. * @template VALUE
  1045. */
  1046. goog.iter.permutations = function(iterable, opt_length) {
  1047. var elements = goog.iter.toArray(iterable);
  1048. var length = goog.isNumber(opt_length) ? opt_length : elements.length;
  1049. var sets = goog.array.repeat(elements, length);
  1050. var product = goog.iter.product.apply(undefined, sets);
  1051. return goog.iter.filter(
  1052. product, function(arr) { return !goog.iter.hasDuplicates_(arr); });
  1053. };
  1054. /**
  1055. * Creates an iterator that returns combinations of elements from
  1056. * {@code iterable}.
  1057. *
  1058. * Combinations are obtained by taking the {@see goog.iter#permutations} of
  1059. * {@code iterable} and filtering those whose elements appear in the order they
  1060. * are encountered in {@code iterable}. For example, the 3-length combinations
  1061. * of {@code [0,1,2,3]} are {@code [[0,1,2], [0,1,3], [0,2,3], [1,2,3]]}.
  1062. * @see http://docs.python.org/2/library/itertools.html#itertools.combinations
  1063. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  1064. * iterable from which to generate combinations.
  1065. * @param {number} length The length of each combination.
  1066. * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing
  1067. * combinations from the {@code iterable}.
  1068. * @template VALUE
  1069. */
  1070. goog.iter.combinations = function(iterable, length) {
  1071. var elements = goog.iter.toArray(iterable);
  1072. var indexes = goog.iter.range(elements.length);
  1073. var indexIterator = goog.iter.permutations(indexes, length);
  1074. // sortedIndexIterator will now give arrays of with the given length that
  1075. // indicate what indexes into "elements" should be returned on each iteration.
  1076. var sortedIndexIterator = goog.iter.filter(
  1077. indexIterator, function(arr) { return goog.array.isSorted(arr); });
  1078. var iter = new goog.iter.Iterator();
  1079. function getIndexFromElements(index) { return elements[index]; }
  1080. iter.next = function() {
  1081. return goog.array.map(sortedIndexIterator.next(), getIndexFromElements);
  1082. };
  1083. return iter;
  1084. };
  1085. /**
  1086. * Creates an iterator that returns combinations of elements from
  1087. * {@code iterable}, with repeated elements possible.
  1088. *
  1089. * Combinations are obtained by taking the Cartesian product of {@code length}
  1090. * iterables and filtering those whose elements appear in the order they are
  1091. * encountered in {@code iterable}. For example, the 2-length combinations of
  1092. * {@code [1,2,3]} are {@code [[1,1], [1,2], [1,3], [2,2], [2,3], [3,3]]}.
  1093. * @see https://goo.gl/C0yXe4
  1094. * @see https://goo.gl/djOCsk
  1095. * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
  1096. * iterable to combine.
  1097. * @param {number} length The length of each combination.
  1098. * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing
  1099. * combinations from the {@code iterable}.
  1100. * @template VALUE
  1101. */
  1102. goog.iter.combinationsWithReplacement = function(iterable, length) {
  1103. var elements = goog.iter.toArray(iterable);
  1104. var indexes = goog.array.range(elements.length);
  1105. var sets = goog.array.repeat(indexes, length);
  1106. var indexIterator = goog.iter.product.apply(undefined, sets);
  1107. // sortedIndexIterator will now give arrays of with the given length that
  1108. // indicate what indexes into "elements" should be returned on each iteration.
  1109. var sortedIndexIterator = goog.iter.filter(
  1110. indexIterator, function(arr) { return goog.array.isSorted(arr); });
  1111. var iter = new goog.iter.Iterator();
  1112. function getIndexFromElements(index) { return elements[index]; }
  1113. iter.next = function() {
  1114. return goog.array.map(
  1115. /** @type {!Array<number>} */
  1116. (sortedIndexIterator.next()), getIndexFromElements);
  1117. };
  1118. return iter;
  1119. };