// LINQ-like Enumerable class wrapping lazy generator chains class Enumerable { constructor(iteratorFn) { this._iteratorFn = iteratorFn; } [Symbol.iterator]() { return this._iteratorFn(); } _chain(generatorFn) { const source = this; return new Enumerable(function* () { yield* generatorFn(source); }); } where(predicate) { return this._chain(function* (source) { for (const item of source) if (predicate(item)) yield item; }); } select(selector) { return this._chain(function* (source) { for (const item of source) yield selector(item); }); } take(count) { count = Math.max(0, count); return this._chain(function* (source) { for (const item of source) { if (count-- <= 0) break; yield item; } }); } skip(count) { count = Math.max(0, count); return this._chain(function* (source) { for (const item of source) { if (count-- > 0) continue; yield item; } }); } isLast() { return this._chain(function* (source) { const iter = source[Symbol.iterator](); let current = iter.next(); let index = 0; while (!current.done) { const next = iter.next(); yield [current.value, next.done, index]; current = next; index++; } }); } forEach(action) { for (const item of this) { if (Array.isArray(item)) { action(...item); } else { action(item); } } } toArray() { return Array.from(this); } firstOrDefault(predicate) { const source = predicate ? this.where(predicate) : this; for (const item of source) return item; return undefined; } first(predicate) { const source = predicate ? this.where(predicate) : this; for (const item of source) return item; throw new Error("No elements in sequence."); } lastOrDefault(predicate) { const source = predicate ? this.where(predicate) : this; let lastValue = undefined; for (const item of source) lastValue = item; return lastValue; } last(predicate) { const source = predicate ? this.where(predicate) : this; let lastValue = undefined; let found = false; for (const item of source) { lastValue = item; found = true; } if (!found) throw new Error("No elements in sequence."); return lastValue; } any(predicate) { const source = predicate ? this.where(predicate) : this; for (const _ of source) return true; return false; } all(predicate) { for (const item of this) if (!predicate(item)) return false; return true; } count(predicate) { let count = 0; const source = predicate ? this.where(predicate) : this; for (const _ of source) count++; return count; } } Array.prototype.asEnumerable = function () { const arr = this; return new Enumerable(function* () { for (const item of arr) yield item; }); }