UNPKG

asclasit

Version:

ASync CLasses + ASync ITerators

259 lines (206 loc) 5.67 kB
const Iter = require('./map'); require('./filter'); const $ = require('../func'); function* chunkByCount(iter, count) { let buf = []; for (const item of iter) { if (buf.push(item) === count) { yield buf; buf = []; } } if (buf.length) yield buf; } function* chunkByCountFunc(iter, count, ...funcs) { $._predicateFuncs(funcs); const desc = {buf: [], idx: 0, iter, ctx: this}; for (const item of iter) { let newChunk = item; for (const func of funcs) { newChunk = func.call(this, newChunk, item, desc); } if (newChunk > 0 && desc.buf.length) { yield desc.buf; desc.buf = []; } if (desc.buf.push(item) === count || newChunk < 0) { yield desc.buf; desc.buf = []; } desc.idx++; } if (desc.buf.length) yield desc.buf; } Iter.chain_(function* chunk(iter, ...funcs) { if (typeof funcs[0] === 'function') yield* chunkByCountFunc(iter, 0, ...funcs); else if (funcs[1] !== undefined) yield* chunkByCountFunc(iter, ...funcs); else yield* chunkByCount(iter, funcs[0]); }); Iter.chain_(function* flatten(iter, depth) { if (depth == null) { depth = 1; } else if (depth === 0) { yield* iter; return; } for (const item of iter) { const it = Iter.getIter(item); if (!it) yield item; else if (depth === 1) yield* it; else yield* flatten(it, depth - 1); } }); function isIter(itrb) { const gen = Iter.getGen(itrb); if (!gen) return [itrb]; const iter = Iter.getIter(gen); return [itrb, iter, itrb != iter && gen, true]; } function countIter(sum, i2) { if (i2[1]) sum++; return sum; } Iter.chain_(function* zipt(...iters) { const l = iters.length; if (!l) return; const its = iters.map(isIter); let active = its.reduce(countIter, 0); let safe; try { while (active) { for (const it of its) { if (it[1]) { safe = true; while (true) { const [, iter, gen, first] = it; let value, done; try { ({value, done} = iter.next()); } catch (err) { it.fill(); throw err; } if (done) { if (first) { active--; it[3] = false; } if (gen && safe) { safe = false; it[1] = Iter.getIter(gen); continue; } else { it.fill(); yield; } } else { yield value; } break; } } else { yield it[0]; } } } /*} catch (err) { for (const [, iter] of its) { if (iter && iter.throw) try { iter.throw(err); } catch (e) { err = e; } } throw err;*/ } finally { for (const [, iter] of its) { if (iter && iter.return) { iter.return(); } } } }); Iter.chain_(function* cut(iter, n) { if (!n || !Number.isInteger(n)) return yield* iter; let cutted; if (n > 0) { cutted = iter; } else { cutted = Iter.map.gen.call(this, iter, n); n = -n; } Iter.ffwd(cutted, n); yield* cutted; }); Iter.chain_(function* zip(...iters) { const l = iters.length; if (!l) return; const zipt = Iter.zipt.gen.call(this, ...iters); const cut = Iter.cut.gen.call(this, zipt, -l); yield* cut; }); function *partialDim(pfx, dim1, dim2, ...dims) { const desc = {iter: dim1, ctx: this}; for (const item of dim1) { const out = [...pfx, item]; if (dim2) { const iter = Iter.getIter.call(this, dim2, false, out, desc); yield* partialDim.call(this, out, iter || [dim2], ...dims); } else { yield out; } } }; Iter.chain_(function *dim(...dims) { const pfx = []; yield* partialDim.call(this, pfx, ...dims); }); Iter.chain_(function* sep(iter, gen, ...funcs) { const desc = {iter, ctx: this}; let idx = 0; for (item of iter) { if (idx) { let v = true; for (const func of funcs) v = func.call(this, v, item, idx, desc); if (v) { const it = Iter.getIter.call(this, gen, false, item, idx, desc); if (it) yield* it; else yield gen; } } yield item; idx++; } }); Iter.chain_(function* sortedWith(inA, inB, func) { const A = Iter.from(inA); const B = Iter.from(inB); let a, b; try { a = A.read(); b = B.read(); while (a !== $.eof && b !== $.eof) { if (func.call(this, a, b) > 0) { yield b; b = B.read(); } else { yield a; a = A.read(); } } if (a === $.eof) while (b !== $.eof) { yield b; b = B.read(); } else while (a !== $.eof) { yield a; a = A.read(); } } finally { try { if (a !== $.eof) A.return(); } catch (err) { } try { if (b !== $.eof) B.return(); } catch (err) { } } }); Iter.value_(function sort(iter, func, opts = {}) { if (typeof func !== 'function') { opts = func; func = $.numSort; } if (typeof opts !== 'object') opts = {limit: opts}; let {skip, limit, desc} = opts; if (skip > 0 && limit > 0) limit += skip; if (limit === 0) { for (const item of iter) break; return []; } if (!(opts.limit > 0)) { const res = Array.from(iter); if (desc) res.sort($.neg_(func)); else res.sort(func); if (skip) return res.slice(skip); return res; } if (opts.filters) iter = Iter.filter.gen.call(this, iter, ...opts.filters); if (opts.filter !== undefined) iter = Iter.filter.gen.call(this, iter, opts.filter); const pq = new $.PQ.Limited({sort: func, limit, reverse: !opts.desc}); for (const item of iter) pq.pushOne(item); const res = pq.toArray(); if (skip) return res.slice(skip); return res; }); module.exports = Iter;