Module

x/linq/linq.js

linq.js - LINQ for JavaScript
Latest
File
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070
/*-------------------------------------------------------------------------- * linq.js - LINQ for JavaScript * licensed under MIT License *------------------------------------------------------------------------*/
var Functions = { Identity: function (x) { return x; }, True: function () { return true; }, Blank: function () { }};
var Types = { Boolean: typeof true, Number: typeof 0, String: typeof "", Object: typeof {}, Undefined: typeof undefined, Function: typeof function () { }};
var funcCache = { "": Functions.Identity };
var Utils = { createLambda: function (expression) { if (expression == null) return Functions.Identity; if (typeof expression === Types.String) { // get from cache let f = funcCache[expression]; if (f != null) { return f; }
if (expression.indexOf("=>") === -1) { const regexp = new RegExp("[$]+", "g");
let maxLength = 0; let match; while ((match = regexp.exec(expression)) != null) { if (match[0].length > maxLength) { maxLength = match[0].length; } }
const argArray = []; for (let i = 1; i <= maxLength; i++) { let dollar = ""; for (let j = 0; j < i; j++) { dollar += "$"; } argArray.push(dollar); }
const args = argArray.join(",");
f = new Function(args, "return " + expression); funcCache[expression] = f; return f; } else { const expr = expression.match(/^[(\s]*([^()]*?)[)\s]*=>(.*)/); f = new Function(expr[1], (expr[2].match(/\breturn\b/) ? expr[2] : "return " + expr[2])); funcCache[expression] = f; return f; } } return expression; },
defineProperty: function (target, methodName, value) { Object.defineProperty(target, methodName, { enumerable: false, configurable: true, writable: true, value: value }) },
compare: function (a, b) { return (a === b) ? 0 : (a > b) ? 1 : -1; },
dispose: function (obj) { if (obj != null) obj.dispose(); },
hasNativeIteratorSupport: function () { return typeof Symbol !== 'undefined' && typeof Symbol.iterator !== 'undefined'; }};
var State = { Before: 0, Running: 1, After: 2 };
var IEnumerator = function (initialize, tryGetNext, dispose) { var yielder = new Yielder(); var state = State.Before;
this.current = yielder.current;
this.moveNext = function () { try { switch (state) { case State.Before: state = State.Running; initialize(); // fall through
case State.Running: if (tryGetNext.apply(yielder)) { return true; } else { this.dispose(); return false; } // fall through
case State.After: return false; } } catch (e) { this.dispose(); throw e; } };
this.dispose = function () { if (state != State.Running) return;
try { dispose(); } finally { state = State.After; } };};
// tryGetNext yieldervar Yielder = function () { var current = null; this.current = function () { return current; }; this.yieldReturn = function (value) { current = value; return true; }; this.yieldBreak = function () { return false; };};
// Enumerable constuctorvar Enumerable = function (getEnumerator) { this.getEnumerator = getEnumerator;};
///////////////////// Utility Methods
Enumerable.Utils = {};
Enumerable.Utils.createLambda = function (expression) { return Utils.createLambda(expression);};
Enumerable.Utils.createEnumerable = function (getEnumerator) { return new Enumerable(getEnumerator);};
Enumerable.Utils.createEnumerator = function (initialize, tryGetNext, dispose) { return new IEnumerator(initialize, tryGetNext, dispose);};
Enumerable.Utils.extendTo = function (type) { var typeProto = type.prototype; var enumerableProto;
if (type === Array) { enumerableProto = ArrayEnumerable.prototype; Utils.defineProperty(typeProto, "getSource", function () { return this; }); } else { enumerableProto = Enumerable.prototype; Utils.defineProperty(typeProto, "getEnumerator", function () { return Enumerable.from(this).getEnumerator(); }); }
for (let methodName in enumerableProto) { const func = enumerableProto[methodName];
// already extended if (typeProto[methodName] == func) continue;
// already defined(example Array#reverse/join/forEach...) if (typeProto[methodName] != null) { methodName = methodName + "ByLinq"; if (typeProto[methodName] == func) continue; // recheck }
if (func instanceof Function) { Utils.defineProperty(typeProto, methodName, func); } }};
Enumerable.Utils.recallFrom = function (type) { var typeProto = type.prototype; var enumerableProto;
if (type === Array) { enumerableProto = ArrayEnumerable.prototype; delete typeProto.getSource; } else { enumerableProto = Enumerable.prototype; delete typeProto.getEnumerator; }
for (const methodName in enumerableProto) { const func = enumerableProto[methodName];
if (typeProto[methodName + 'ByLinq']) { delete typeProto[methodName + 'ByLinq']; } else if (typeProto[methodName] == func && func instanceof Function) { delete typeProto[methodName]; } }};
//////////////// Generators
Enumerable.choice = function () { var args = arguments;
return new Enumerable(function () { return new IEnumerator( function () { args = (args[0] instanceof Array) ? args[0] : (args[0].getEnumerator != null) ? args[0].toArray() : args; }, function () { return this.yieldReturn(args[Math.floor(Math.random() * args.length)]); }, Functions.Blank); });};
Enumerable.cycle = function () { var args = arguments;
return new Enumerable(function () { var index = 0; return new IEnumerator( function () { args = (args[0] instanceof Array) ? args[0] : (args[0].getEnumerator != null) ? args[0].toArray() : args; }, function () { if (index >= args.length) index = 0; return this.yieldReturn(args[index++]); }, Functions.Blank); });};
Enumerable.empty = function () { return new Enumerable(function () { return new IEnumerator( Functions.Blank, function () { return false; }, Functions.Blank); });};
Enumerable.from = function (obj) { if (obj == null) { return Enumerable.empty(); } if (obj instanceof Enumerable) { return obj; } if (typeof obj == Types.Number || typeof obj == Types.Boolean) { return Enumerable.repeat(obj, 1); } if (typeof obj == Types.String) { return new Enumerable(function () { var index = 0; return new IEnumerator( Functions.Blank, function () { return (index < obj.length) ? this.yieldReturn(obj.charAt(index++)) : false; }, Functions.Blank); }); } if (typeof obj == Types.Function && Object.keys(obj).length == 0) { return new Enumerable(function () { var orig;
return new IEnumerator( function () { orig = obj()[Symbol.iterator](); }, function () { var next = orig.next(); return (next.done ? false : (this.yieldReturn(next.value))); }, Functions.Blank); }); }
if (typeof obj != Types.Function) { // array or array-like object if (typeof obj.length == Types.Number) { return new ArrayEnumerable(obj); }
// iterable object if (typeof Symbol !== 'undefined' && typeof obj[Symbol.iterator] !== 'undefined') { return new Enumerable(function () { return new IEnumerator( Functions.Blank, function () { var next = obj.next(); return (next.done ? false : (this.yieldReturn(next.value))); }, Functions.Blank); }); } }
// case function/object: create keyValuePair[] return new Enumerable(function () { var array = []; var index = 0;
return new IEnumerator( function () { for (const key in obj) { const value = obj[key]; if (!(value instanceof Function) && Object.prototype.hasOwnProperty.call(obj, key)) { array.push({ key: key, value: value }); } } }, function () { return (index < array.length) ? this.yieldReturn(array[index++]) : false; }, Functions.Blank); });},
Enumerable.make = function (element) { return Enumerable.repeat(element, 1); };
// Overload:function(input, pattern)// Overload:function(input, pattern, flags)Enumerable.matches = function (input, pattern, flags) { if (flags == null) flags = "";
if (pattern instanceof RegExp) { flags += (pattern.ignoreCase) ? "i" : ""; flags += (pattern.multiline) ? "m" : ""; pattern = pattern.source; } if (flags.indexOf("g") === -1) flags += "g";
return new Enumerable(function () { var regex; return new IEnumerator( function () { regex = new RegExp(pattern, flags); }, function () { var match = regex.exec(input); return (match) ? this.yieldReturn(match) : false; }, Functions.Blank); });};
// Overload:function(start, count)// Overload:function(start, count, step)Enumerable.range = function (start, count, step) { if (step == null) step = 1;
return new Enumerable(function () { var value; var index = 0;
return new IEnumerator( function () { value = start - step; }, function () { return (index++ < count) ? this.yieldReturn(value += step) : this.yieldBreak(); }, Functions.Blank); });};
// Overload:function(start, count)// Overload:function(start, count, step)Enumerable.rangeDown = function (start, count, step) { if (step == null) step = 1;
return new Enumerable(function () { var value; var index = 0;
return new IEnumerator( function () { value = start + step; }, function () { return (index++ < count) ? this.yieldReturn(value -= step) : this.yieldBreak(); }, Functions.Blank); });};
// Overload:function(start, to)// Overload:function(start, to, step)Enumerable.rangeTo = function (start, to, step) { if (step == null) step = 1;
if (start < to) { return new Enumerable(function () { var value;
return new IEnumerator( function () { value = start - step; }, function () { var next = value += step; return (next <= to) ? this.yieldReturn(next) : this.yieldBreak(); }, Functions.Blank); }); } else { return new Enumerable(function () { var value;
return new IEnumerator( function () { value = start + step; }, function () { var next = value -= step; return (next >= to) ? this.yieldReturn(next) : this.yieldBreak(); }, Functions.Blank); }); }};
// Overload:function(element)// Overload:function(element, count)Enumerable.repeat = function (element, count) { if (count != null) return Enumerable.repeat(element).take(count);
return new Enumerable(function () { return new IEnumerator( Functions.Blank, function () { return this.yieldReturn(element); }, Functions.Blank); });};
Enumerable.repeatWithFinalize = function (initializer, finalizer) { initializer = Utils.createLambda(initializer); finalizer = Utils.createLambda(finalizer);
return new Enumerable(function () { var element; return new IEnumerator( function () { element = initializer(); }, function () { return this.yieldReturn(element); }, function () { if (element != null) { finalizer(element); element = null; } }); });};
// Overload:function(func)// Overload:function(func, count)Enumerable.generate = function (func, count) { if (count != null) return Enumerable.generate(func).take(count);
func = Utils.createLambda(func);
return new Enumerable(function () { return new IEnumerator( Functions.Blank, function () { return this.yieldReturn(func()); }, Functions.Blank); });};
// Overload:function()// Overload:function(start)// Overload:function(start, step)Enumerable.toInfinity = function (start, step) { if (start == null) start = 0; if (step == null) step = 1;
return new Enumerable(function () { var value; return new IEnumerator( function () { value = start - step; }, function () { return this.yieldReturn(value += step); }, Functions.Blank); });};
// Overload:function()// Overload:function(start)// Overload:function(start, step)Enumerable.toNegativeInfinity = function (start, step) { if (start == null) start = 0; if (step == null) step = 1;
return new Enumerable(function () { var value; return new IEnumerator( function () { value = start + step; }, function () { return this.yieldReturn(value -= step); }, Functions.Blank); });};
Enumerable.unfold = function (seed, func) { func = Utils.createLambda(func);
return new Enumerable(function () { var isFirst = true; var value; return new IEnumerator( Functions.Blank, function () { if (isFirst) { isFirst = false; value = seed; return this.yieldReturn(value); } value = func(value); return this.yieldReturn(value); }, Functions.Blank); });};
Enumerable.defer = function (enumerableFactory) { return new Enumerable(function () { var enumerator;
return new IEnumerator( function () { enumerator = Enumerable.from(enumerableFactory()).getEnumerator(); }, function () { return (enumerator.moveNext()) ? this.yieldReturn(enumerator.current()) : this.yieldBreak(); }, function () { Utils.dispose(enumerator); }); });};
/////////////////////// Extension Methods
////////////////////////////////////// Projection and Filtering Methods
// Overload:function(func)// Overload:function(func, resultSelector<element>)// Overload:function(func, resultSelector<element, nestLevel>)Enumerable.prototype.traverseBreadthFirst = function (func, resultSelector) { var source = this; func = Utils.createLambda(func); resultSelector = Utils.createLambda(resultSelector);
return new Enumerable(function () { var enumerator; var nestLevel = 0; var buffer = [];
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { while (true) { if (enumerator.moveNext()) { buffer.push(enumerator.current()); return this.yieldReturn(resultSelector(enumerator.current(), nestLevel)); }
const next = Enumerable.from(buffer).selectMany(function (x) { return func(x); }); if (!next.any()) { return false; } else { nestLevel++; buffer = []; Utils.dispose(enumerator); enumerator = next.getEnumerator(); } } }, function () { Utils.dispose(enumerator); }); });};
// Overload:function(func)// Overload:function(func, resultSelector<element>)// Overload:function(func, resultSelector<element, nestLevel>)Enumerable.prototype.traverseDepthFirst = function (func, resultSelector) { var source = this; func = Utils.createLambda(func); resultSelector = Utils.createLambda(resultSelector);
return new Enumerable(function () { var enumeratorStack = []; var enumerator;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { while (true) { if (enumerator.moveNext()) { const value = resultSelector(enumerator.current(), enumeratorStack.length); enumeratorStack.push(enumerator); enumerator = Enumerable.from(func(enumerator.current())).getEnumerator(); return this.yieldReturn(value); }
if (enumeratorStack.length <= 0) return false; Utils.dispose(enumerator); enumerator = enumeratorStack.pop(); } }, function () { try { Utils.dispose(enumerator); } finally { Enumerable.from(enumeratorStack).forEach(function (s) { s.dispose(); }); } }); });};
Enumerable.prototype.flatten = function () { var source = this;
return new Enumerable(function () { var enumerator; var middleEnumerator = null;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { while (true) { if (middleEnumerator != null) { if (middleEnumerator.moveNext()) { return this.yieldReturn(middleEnumerator.current()); } else { middleEnumerator = null; } }
if (enumerator.moveNext()) { if (enumerator.current() instanceof Array) { Utils.dispose(middleEnumerator); middleEnumerator = Enumerable.from(enumerator.current()) .selectMany(Functions.Identity) .flatten() .getEnumerator(); continue; } else { return this.yieldReturn(enumerator.current()); } }
return false; } }, function () { try { Utils.dispose(enumerator); } finally { Utils.dispose(middleEnumerator); } }); });};
Enumerable.prototype.pairwise = function (selector) { var source = this; selector = Utils.createLambda(selector);
return new Enumerable(function () { var enumerator;
return new IEnumerator( function () { enumerator = source.getEnumerator(); enumerator.moveNext(); }, function () { var prev = enumerator.current(); return (enumerator.moveNext()) ? this.yieldReturn(selector(prev, enumerator.current())) : false; }, function () { Utils.dispose(enumerator); }); });};
// Overload:function(func)// Overload:function(seed,func<value,element>)Enumerable.prototype.scan = function (seed, func) { var isUseSeed; if (func == null) { func = Utils.createLambda(seed); isUseSeed = false; } else { func = Utils.createLambda(func); isUseSeed = true; } var source = this;
return new Enumerable(function () { var enumerator; var value; var isFirst = true;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { if (isFirst) { isFirst = false; if (!isUseSeed) { if (enumerator.moveNext()) { return this.yieldReturn(value = enumerator.current()); } } else { return this.yieldReturn(value = seed); } }
return (enumerator.moveNext()) ? this.yieldReturn(value = func(value, enumerator.current())) : false; }, function () { Utils.dispose(enumerator); }); });};
// Overload:function(selector<element>)// Overload:function(selector<element,index>)Enumerable.prototype.select = function (selector) { selector = Utils.createLambda(selector);
if (selector.length <= 1) { return new WhereSelectEnumerable(this, null, selector); } else { var source = this;
return new Enumerable(function () { var enumerator; var index = 0;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { return (enumerator.moveNext()) ? this.yieldReturn(selector(enumerator.current(), index++)) : false; }, function () { Utils.dispose(enumerator); }); }); }};
// Overload:function(collectionSelector<element>)// Overload:function(collectionSelector<element,index>)// Overload:function(collectionSelector<element>,resultSelector)// Overload:function(collectionSelector<element,index>,resultSelector)Enumerable.prototype.selectMany = function (collectionSelector, resultSelector) { var source = this; collectionSelector = Utils.createLambda(collectionSelector); if (resultSelector == null) resultSelector = function (a, b) { return b; }; resultSelector = Utils.createLambda(resultSelector);
return new Enumerable(function () { var enumerator; var middleEnumerator = undefined; var index = 0;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { if (middleEnumerator === undefined) { if (!enumerator.moveNext()) return false; } do { if (middleEnumerator == null) { const middleSeq = collectionSelector(enumerator.current(), index++); middleEnumerator = Enumerable.from(middleSeq).getEnumerator(); } if (middleEnumerator.moveNext()) { return this.yieldReturn(resultSelector(enumerator.current(), middleEnumerator.current())); } Utils.dispose(middleEnumerator); middleEnumerator = null; } while (enumerator.moveNext()); return false; }, function () { try { Utils.dispose(enumerator); } finally { Utils.dispose(middleEnumerator); } }); });};
// Overload:function(predicate<element>)// Overload:function(predicate<element,index>)Enumerable.prototype.where = function (predicate) { predicate = Utils.createLambda(predicate);
if (predicate.length <= 1) { return new WhereEnumerable(this, predicate); } else { var source = this;
return new Enumerable(function () { var enumerator; var index = 0;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { while (enumerator.moveNext()) { if (predicate(enumerator.current(), index++)) { return this.yieldReturn(enumerator.current()); } } return false; }, function () { Utils.dispose(enumerator); }); }); }};

// Overload:function(selector<element>)// Overload:function(selector<element,index>)Enumerable.prototype.choose = function (selector) { selector = Utils.createLambda(selector); var source = this;
return new Enumerable(function () { var enumerator; var index = 0;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { while (enumerator.moveNext()) { const result = selector(enumerator.current(), index++); if (result != null) { return this.yieldReturn(result); } } return this.yieldBreak(); }, function () { Utils.dispose(enumerator); }); });};
Enumerable.prototype.ofType = function (type) { var typeName; switch (type) { case Number: typeName = Types.Number; break; case String: typeName = Types.String; break; case Boolean: typeName = Types.Boolean; break; case Function: typeName = Types.Function; break; default: typeName = null; break; } return (typeName === null) ? this.where(function (x) { return x instanceof type; }) : this.where(function (x) { return typeof x === typeName; });};
// mutiple arguments, last one is selector, others are enumerableEnumerable.prototype.zip = function () { var args = arguments; var selector = Utils.createLambda(arguments[arguments.length - 1]);
var source = this; // optimized case:argument is 2 if (arguments.length == 2) { const second = arguments[0];
return new Enumerable(function () { var firstEnumerator; var secondEnumerator; var index = 0;
return new IEnumerator( function () { firstEnumerator = source.getEnumerator(); secondEnumerator = Enumerable.from(second).getEnumerator(); }, function () { if (firstEnumerator.moveNext() && secondEnumerator.moveNext()) { return this.yieldReturn(selector(firstEnumerator.current(), secondEnumerator.current(), index++)); } return false; }, function () { try { Utils.dispose(firstEnumerator); } finally { Utils.dispose(secondEnumerator); } }); }); } else { return new Enumerable(function () { var enumerators; var index = 0;
return new IEnumerator( function () { var array = Enumerable.make(source) .concat(Enumerable.from(args).takeExceptLast().select(Enumerable.from)) .select(function (x) { return x.getEnumerator() }) .toArray(); enumerators = Enumerable.from(array); }, function () { if (enumerators.all(function (x) { return x.moveNext() })) { const array = enumerators .select(function (x) { return x.current() }) .toArray(); array.push(index++); return this.yieldReturn(selector.apply(null, array)); } else { return this.yieldBreak(); } }, function () { Enumerable.from(enumerators).forEach(Utils.dispose); }); }); }};
// mutiple argumentsEnumerable.prototype.merge = function () { var args = arguments; var source = this;
return new Enumerable(function () { var enumerators; var index = -1;
return new IEnumerator( function () { enumerators = Enumerable.make(source) .concat(Enumerable.from(args).select(Enumerable.from)) .select(function (x) { return x.getEnumerator() }) .toArray(); }, function () { while (enumerators.length > 0) { index = (index >= enumerators.length - 1) ? 0 : index + 1; const enumerator = enumerators[index];
if (enumerator.moveNext()) { return this.yieldReturn(enumerator.current()); } else { enumerator.dispose(); enumerators.splice(index--, 1); } } return this.yieldBreak(); }, function () { Enumerable.from(enumerators).forEach(Utils.dispose); }); });};
////////////////// Join Methods
// Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector)// Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector)Enumerable.prototype.join = function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) { outerKeySelector = Utils.createLambda(outerKeySelector); innerKeySelector = Utils.createLambda(innerKeySelector); resultSelector = Utils.createLambda(resultSelector); compareSelector = Utils.createLambda(compareSelector); var source = this;
return new Enumerable(function () { var outerEnumerator; var lookup; var innerElements = null; var innerCount = 0;
return new IEnumerator( function () { outerEnumerator = source.getEnumerator(); lookup = Enumerable.from(inner).toLookup(innerKeySelector, Functions.Identity, compareSelector); }, function () { while (true) { if (innerElements != null) { let innerElement = innerElements[innerCount++]; if (innerElement !== undefined) { return this.yieldReturn(resultSelector(outerEnumerator.current(), innerElement)); }
innerElement = null; innerCount = 0; }
if (outerEnumerator.moveNext()) { const key = outerKeySelector(outerEnumerator.current()); innerElements = lookup.get(key).toArray(); } else { return false; } } }, function () { Utils.dispose(outerEnumerator); }); });};
// Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector)// Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector)Enumerable.prototype.leftJoin = function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) { outerKeySelector = Utils.createLambda(outerKeySelector); innerKeySelector = Utils.createLambda(innerKeySelector); resultSelector = Utils.createLambda(resultSelector); compareSelector = Utils.createLambda(compareSelector); var source = this;
return new Enumerable(function () { var outerEnumerator; var lookup; var innerElements = null; var innerCount = 0;
return new IEnumerator( function () { outerEnumerator = source.getEnumerator(); lookup = Enumerable.from(inner).toLookup(innerKeySelector, Functions.Identity, compareSelector); }, function () { while (true) { if (innerElements != null) { let innerElement = innerElements[innerCount++]; if (innerElement !== undefined) { return this.yieldReturn(resultSelector(outerEnumerator.current(), innerElement)); }
innerElement = null; innerCount = 0; }
if (outerEnumerator.moveNext()) { const key = outerKeySelector(outerEnumerator.current()); innerElements = lookup.get(key).toArray(); // execute once if innerElements is NULL if (innerElements == null || innerElements.length == 0) { return this.yieldReturn(resultSelector(outerEnumerator.current(), null)); } } else { return false; } } }, function () { Utils.dispose(outerEnumerator); }); });};
// Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector)// Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector)Enumerable.prototype.groupJoin = function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) { outerKeySelector = Utils.createLambda(outerKeySelector); innerKeySelector = Utils.createLambda(innerKeySelector); resultSelector = Utils.createLambda(resultSelector); compareSelector = Utils.createLambda(compareSelector); var source = this;
return new Enumerable(function () { var enumerator = source.getEnumerator(); var lookup = null;
return new IEnumerator( function () { enumerator = source.getEnumerator(); lookup = Enumerable.from(inner).toLookup(innerKeySelector, Functions.Identity, compareSelector); }, function () { if (enumerator.moveNext()) { const innerElement = lookup.get(outerKeySelector(enumerator.current())); return this.yieldReturn(resultSelector(enumerator.current(), innerElement)); } return false; }, function () { Utils.dispose(enumerator); }); });};
///////////////// Set Methods
Enumerable.prototype.all = function (predicate) { predicate = Utils.createLambda(predicate);
var result = true; this.forEach(function (x) { if (!predicate(x)) { result = false; return false; // break } }); return result;};
// Overload:function()// Overload:function(predicate)Enumerable.prototype.any = function (predicate) { predicate = Utils.createLambda(predicate);
var enumerator = this.getEnumerator(); try { if (arguments.length == 0) return enumerator.moveNext(); // case:function()
while (enumerator.moveNext()) // case:function(predicate) { if (predicate(enumerator.current())) return true; } return false; } finally { Utils.dispose(enumerator); }};
Enumerable.prototype.isEmpty = function () { return !this.any();};
// multiple argumentsEnumerable.prototype.concat = function () { var source = this;
if (arguments.length == 1) { const second = arguments[0];
return new Enumerable(function () { var firstEnumerator; var secondEnumerator;
return new IEnumerator( function () { firstEnumerator = source.getEnumerator(); }, function () { if (secondEnumerator == null) { if (firstEnumerator.moveNext()) return this.yieldReturn(firstEnumerator.current()); secondEnumerator = Enumerable.from(second).getEnumerator(); } if (secondEnumerator.moveNext()) return this.yieldReturn(secondEnumerator.current()); return false; }, function () { try { Utils.dispose(firstEnumerator); } finally { Utils.dispose(secondEnumerator); } }); }); } else { const args = arguments;
return new Enumerable(function () { var enumerators;
return new IEnumerator( function () { enumerators = Enumerable.make(source) .concat(Enumerable.from(args).select(Enumerable.from)) .select(function (x) { return x.getEnumerator() }) .toArray(); }, function () { while (enumerators.length > 0) { const enumerator = enumerators[0];
if (enumerator.moveNext()) { return this.yieldReturn(enumerator.current()); } else { enumerator.dispose(); enumerators.splice(0, 1); } } return this.yieldBreak(); }, function () { Enumerable.from(enumerators).forEach(Utils.dispose); }); }); }};
Enumerable.prototype.insert = function (index, second) { var source = this;
return new Enumerable(function () { var firstEnumerator; var secondEnumerator; var count = 0; var isEnumerated = false;
return new IEnumerator( function () { firstEnumerator = source.getEnumerator(); secondEnumerator = Enumerable.from(second).getEnumerator(); }, function () { if (count == index && secondEnumerator.moveNext()) { isEnumerated = true; return this.yieldReturn(secondEnumerator.current()); } if (firstEnumerator.moveNext()) { count++; return this.yieldReturn(firstEnumerator.current()); } if (!isEnumerated && secondEnumerator.moveNext()) { return this.yieldReturn(secondEnumerator.current()); } return false; }, function () { try { Utils.dispose(firstEnumerator); } finally { Utils.dispose(secondEnumerator); } }); });};
Enumerable.prototype.alternate = function (alternateValueOrSequence) { var source = this;
return new Enumerable(function () { var buffer; var enumerator; var alternateSequence; var alternateEnumerator;
return new IEnumerator( function () { if (alternateValueOrSequence instanceof Array || alternateValueOrSequence.getEnumerator != null) { alternateSequence = Enumerable.from(Enumerable.from(alternateValueOrSequence).toArray()); // freeze } else { alternateSequence = Enumerable.make(alternateValueOrSequence); } enumerator = source.getEnumerator(); if (enumerator.moveNext()) buffer = enumerator.current(); }, function () { while (true) { if (alternateEnumerator != null) { if (alternateEnumerator.moveNext()) { return this.yieldReturn(alternateEnumerator.current()); } else { alternateEnumerator = null; } }
if (buffer == null && enumerator.moveNext()) { buffer = enumerator.current(); // hasNext alternateEnumerator = alternateSequence.getEnumerator(); continue; // GOTO } else if (buffer != null) { const retVal = buffer; buffer = null; return this.yieldReturn(retVal); }
return this.yieldBreak(); } }, function () { try { Utils.dispose(enumerator); } finally { Utils.dispose(alternateEnumerator); } }); });};
// Overload:function(value)// Overload:function(value, compareSelector)Enumerable.prototype.contains = function (value, compareSelector) { compareSelector = Utils.createLambda(compareSelector); var enumerator = this.getEnumerator(); try { while (enumerator.moveNext()) { if (compareSelector(enumerator.current()) === value) return true; } return false; } finally { Utils.dispose(enumerator); }};
Enumerable.prototype.defaultIfEmpty = function (defaultValue) { var source = this; if (defaultValue === undefined) defaultValue = null;
return new Enumerable(function () { var enumerator; var isFirst = true;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { if (enumerator.moveNext()) { isFirst = false; return this.yieldReturn(enumerator.current()); } else if (isFirst) { isFirst = false; return this.yieldReturn(defaultValue); } return false; }, function () { Utils.dispose(enumerator); }); });};
// Overload:function()// Overload:function(compareSelector)Enumerable.prototype.distinct = function (compareSelector) { return this.except(Enumerable.empty(), compareSelector);};
Enumerable.prototype.distinctUntilChanged = function (compareSelector) { compareSelector = Utils.createLambda(compareSelector); var source = this;
return new Enumerable(function () { var enumerator; var compareKey; var initial;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { while (enumerator.moveNext()) { const key = compareSelector(enumerator.current());
if (initial) { initial = false; compareKey = key; return this.yieldReturn(enumerator.current()); }
if (compareKey === key) { continue; }
compareKey = key; return this.yieldReturn(enumerator.current()); } return this.yieldBreak(); }, function () { Utils.dispose(enumerator); }); });};
// Overload:function(second)// Overload:function(second, compareSelector)Enumerable.prototype.except = function (second, compareSelector) { compareSelector = Utils.createLambda(compareSelector); var source = this;
return new Enumerable(function () { var enumerator; var keys;
return new IEnumerator( function () { enumerator = source.getEnumerator(); keys = new Dictionary(compareSelector); Enumerable.from(second).forEach(function (key) { keys.add(key); }); }, function () { while (enumerator.moveNext()) { const current = enumerator.current(); if (!keys.contains(current)) { keys.add(current); return this.yieldReturn(current); } } return false; }, function () { Utils.dispose(enumerator); }); });};
// Overload:function(second)// Overload:function(second, compareSelector)Enumerable.prototype.intersect = function (second, compareSelector) { compareSelector = Utils.createLambda(compareSelector); var source = this;
return new Enumerable(function () { var enumerator; var keys; var outs;
return new IEnumerator( function () { enumerator = source.getEnumerator();
keys = new Dictionary(compareSelector); Enumerable.from(second).forEach(function (key) { keys.add(key); }); outs = new Dictionary(compareSelector); }, function () { while (enumerator.moveNext()) { const current = enumerator.current(); if (!outs.contains(current) && keys.contains(current)) { outs.add(current); return this.yieldReturn(current); } } return false; }, function () { Utils.dispose(enumerator); }); });};
// Overload:function(second)// Overload:function(second, compareSelector)Enumerable.prototype.sequenceEqual = function (second, compareSelector) { compareSelector = Utils.createLambda(compareSelector);
var firstEnumerator = this.getEnumerator(); try { const secondEnumerator = Enumerable.from(second).getEnumerator(); try { while (firstEnumerator.moveNext()) { if (!secondEnumerator.moveNext() || compareSelector(firstEnumerator.current()) !== compareSelector(secondEnumerator.current())) { return false; } }
if (secondEnumerator.moveNext()) return false; return true; } finally { Utils.dispose(secondEnumerator); } } finally { Utils.dispose(firstEnumerator); }};
Enumerable.prototype.union = function (second, compareSelector) { compareSelector = Utils.createLambda(compareSelector); var source = this;
return new Enumerable(function () { var firstEnumerator; var secondEnumerator; var keys;
return new IEnumerator( function () { firstEnumerator = source.getEnumerator(); keys = new Dictionary(compareSelector); }, function () { var current; if (secondEnumerator === undefined) { while (firstEnumerator.moveNext()) { current = firstEnumerator.current(); if (!keys.contains(current)) { keys.add(current); return this.yieldReturn(current); } } secondEnumerator = Enumerable.from(second).getEnumerator(); } while (secondEnumerator.moveNext()) { current = secondEnumerator.current(); if (!keys.contains(current)) { keys.add(current); return this.yieldReturn(current); } } return false; }, function () { try { Utils.dispose(firstEnumerator); } finally { Utils.dispose(secondEnumerator); } }); });};
////////////////////// Ordering Methods
Enumerable.prototype.orderBy = function (keySelector, comparer) { return new OrderedEnumerable(this, keySelector, comparer, false);};
Enumerable.prototype.orderByDescending = function (keySelector, comparer) { return new OrderedEnumerable(this, keySelector, comparer, true);};
Enumerable.prototype.reverse = function () { var source = this;
return new Enumerable(function () { var buffer; var index;
return new IEnumerator( function () { buffer = source.toArray(); index = buffer.length; }, function () { return (index > 0) ? this.yieldReturn(buffer[--index]) : false; }, Functions.Blank); });};
Enumerable.prototype.shuffle = function () { var source = this;
return new Enumerable(function () { var buffer;
return new IEnumerator( function () { buffer = source.toArray(); }, function () { if (buffer.length > 0) { const i = Math.floor(Math.random() * buffer.length); return this.yieldReturn(buffer.splice(i, 1)[0]); } return false; }, Functions.Blank); });};
Enumerable.prototype.weightedSample = function (weightSelector) { weightSelector = Utils.createLambda(weightSelector); var source = this;
return new Enumerable(function () { var sortedByBound; var totalWeight = 0;
return new IEnumerator( function () { sortedByBound = source .choose(function (x) { var weight = weightSelector(x); if (weight <= 0) return null; // ignore 0
totalWeight += weight; return { value: x, bound: totalWeight }; }) .toArray(); }, function () { if (sortedByBound.length > 0) { const draw = Math.floor(Math.random() * totalWeight) + 1;
let lower = -1; let upper = sortedByBound.length; while (upper - lower > 1) { const index = Math.floor((lower + upper) / 2); if (sortedByBound[index].bound >= draw) { upper = index; } else { lower = index; } }
return this.yieldReturn(sortedByBound[upper].value); }
return this.yieldBreak(); }, Functions.Blank); });};
////////////////////// Grouping Methods
// Overload:function(keySelector)// Overload:function(keySelector,elementSelector)// Overload:function(keySelector,elementSelector,resultSelector)// Overload:function(keySelector,elementSelector,resultSelector,compareSelector)Enumerable.prototype.groupBy = function (keySelector, elementSelector, resultSelector, compareSelector) { var source = this; keySelector = Utils.createLambda(keySelector); elementSelector = Utils.createLambda(elementSelector); if (resultSelector != null) resultSelector = Utils.createLambda(resultSelector); compareSelector = Utils.createLambda(compareSelector);
return new Enumerable(function () { var enumerator;
return new IEnumerator( function () { enumerator = source.toLookup(keySelector, elementSelector, compareSelector) .toEnumerable() .getEnumerator(); }, function () { while (enumerator.moveNext()) { return (resultSelector == null) ? this.yieldReturn(enumerator.current()) : this.yieldReturn(resultSelector(enumerator.current().key(), enumerator.current())); } return false; }, function () { Utils.dispose(enumerator); }); });};
// Overload:function(keySelector)// Overload:function(keySelector,elementSelector)// Overload:function(keySelector,elementSelector,resultSelector)// Overload:function(keySelector,elementSelector,resultSelector,compareSelector)Enumerable.prototype.partitionBy = function (keySelector, elementSelector, resultSelector, compareSelector) { var source = this; keySelector = Utils.createLambda(keySelector); elementSelector = Utils.createLambda(elementSelector); compareSelector = Utils.createLambda(compareSelector); var hasResultSelector; if (resultSelector == null) { hasResultSelector = false; resultSelector = function (key, group) { return new Grouping(key, group); }; } else { hasResultSelector = true; resultSelector = Utils.createLambda(resultSelector); }
return new Enumerable(function () { var enumerator; var key; var compareKey; var group = [];
return new IEnumerator( function () { enumerator = source.getEnumerator(); if (enumerator.moveNext()) { key = keySelector(enumerator.current()); compareKey = compareSelector(key); group.push(elementSelector(enumerator.current())); } }, function () { var hasNext; while ((hasNext = enumerator.moveNext()) == true) { if (compareKey === compareSelector(keySelector(enumerator.current()))) { group.push(elementSelector(enumerator.current())); } else break; }
if (group.length > 0) { const result = (hasResultSelector) ? resultSelector(key, Enumerable.from(group)) : resultSelector(key, group); if (hasNext) { key = keySelector(enumerator.current()); compareKey = compareSelector(key); group = [elementSelector(enumerator.current())]; } else group = [];
return this.yieldReturn(result); }
return false; }, function () { Utils.dispose(enumerator); }); });};
Enumerable.prototype.buffer = function (count) { var source = this;
return new Enumerable(function () { var enumerator;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { var array = []; var index = 0; while (enumerator.moveNext()) { array.push(enumerator.current()); if (++index >= count) return this.yieldReturn(array); } if (array.length > 0) return this.yieldReturn(array); return false; }, function () { Utils.dispose(enumerator); }); });};
/////////////////////// Aggregate Methods
// Overload:function(func)// Overload:function(seed,func)// Overload:function(seed,func,resultSelector)Enumerable.prototype.aggregate = function (seed, func, resultSelector) { resultSelector = Utils.createLambda(resultSelector); return resultSelector(this.scan(seed, func, resultSelector).last());};
// Overload:function()// Overload:function(selector)Enumerable.prototype.average = function (selector) { selector = Utils.createLambda(selector);
var sum = 0; var count = 0; this.forEach(function (x) { sum += selector(x); ++count; });
return sum / count;};
// Overload:function()// Overload:function(predicate)Enumerable.prototype.count = function (predicate) { predicate = (predicate == null) ? Functions.True : Utils.createLambda(predicate);
var count = 0; this.forEach(function (x, i) { if (predicate(x, i)) ++count; }); return count;};
// Overload:function()// Overload:function(selector)Enumerable.prototype.max = function (selector) { if (selector == null) selector = Functions.Identity; return this.select(selector).aggregate(function (a, b) { return (a > b) ? a : b; });};
// Overload:function()// Overload:function(selector)Enumerable.prototype.min = function (selector) { if (selector == null) selector = Functions.Identity; return this.select(selector).aggregate(function (a, b) { return (a < b) ? a : b; });};
Enumerable.prototype.maxBy = function (keySelector) { keySelector = Utils.createLambda(keySelector); return this.aggregate(function (a, b) { return (keySelector(a) > keySelector(b)) ? a : b; });};
Enumerable.prototype.minBy = function (keySelector) { keySelector = Utils.createLambda(keySelector); return this.aggregate(function (a, b) { return (keySelector(a) < keySelector(b)) ? a : b; });};
// Overload:function()// Overload:function(selector)Enumerable.prototype.sum = function (selector) { if (selector == null) selector = Functions.Identity; return this.select(selector).aggregate(0, function (a, b) { return a + b; });};
//////////////////// Paging Methods
Enumerable.prototype.elementAt = function (index) { var value; var found = false; this.forEach(function (x, i) { if (i == index) { value = x; found = true; return false; } });
if (!found) throw new Error("index is less than 0 or greater than or equal to the number of elements in source."); return value;};
Enumerable.prototype.elementAtOrDefault = function (index, defaultValue) { if (defaultValue === undefined) defaultValue = null; var value; var found = false; this.forEach(function (x, i) { if (i == index) { value = x; found = true; return false; } });
return (!found) ? defaultValue : value;};
// Overload:function()// Overload:function(predicate)Enumerable.prototype.first = function (predicate) { if (predicate != null) return this.where(predicate).first();
var value; var found = false; this.forEach(function (x) { value = x; found = true; return false; });
if (!found) throw new Error("first:No element satisfies the condition."); return value;};
Enumerable.prototype.firstOrDefault = function (predicate, defaultValue) { if (predicate !== undefined) { if (typeof predicate === Types.Function || typeof Utils.createLambda(predicate) === Types.Function) { return this.where(predicate).firstOrDefault(undefined, defaultValue); } defaultValue = predicate; }
var value; var found = false; this.forEach(function (x) { value = x; found = true; return false; }); return (!found) ? defaultValue : value;};
// Overload:function()// Overload:function(predicate)Enumerable.prototype.last = function (predicate) { if (predicate != null) return this.where(predicate).last();
var value; var found = false; this.forEach(function (x) { found = true; value = x; });
if (!found) throw new Error("last:No element satisfies the condition."); return value;};
Enumerable.prototype.lastOrDefault = function (predicate, defaultValue) { if (predicate !== undefined) { if (typeof predicate === Types.Function || typeof Utils.createLambda(predicate) === Types.Function) { return this.where(predicate).lastOrDefault(undefined, defaultValue); } defaultValue = predicate; }
var value; var found = false; this.forEach(function (x) { found = true; value = x; }); return (!found) ? defaultValue : value;};
// Overload:function()// Overload:function(predicate)Enumerable.prototype.single = function (predicate) { if (predicate != null) return this.where(predicate).single();
var value; var found = false; this.forEach(function (x) { if (!found) { found = true; value = x; } else throw new Error("single:sequence contains more than one element."); });
if (!found) throw new Error("single:No element satisfies the condition."); return value;};
// Overload:function(defaultValue)// Overload:function(defaultValue,predicate)Enumerable.prototype.singleOrDefault = function (predicate, defaultValue) { if (defaultValue === undefined) defaultValue = null; if (predicate != null) return this.where(predicate).singleOrDefault(null, defaultValue);
var value; var found = false; this.forEach(function (x) { if (!found) { found = true; value = x; } else throw new Error("single:sequence contains more than one element."); });
return (!found) ? defaultValue : value;};
Enumerable.prototype.skip = function (count) { var source = this;
return new Enumerable(function () { var enumerator; var index = 0;
return new IEnumerator( function () { enumerator = source.getEnumerator(); while (index++ < count && enumerator.moveNext()) { } }, function () { return (enumerator.moveNext()) ? this.yieldReturn(enumerator.current()) : false; }, function () { Utils.dispose(enumerator); }); });};
// Overload:function(predicate<element>)// Overload:function(predicate<element,index>)Enumerable.prototype.skipWhile = function (predicate) { predicate = Utils.createLambda(predicate); var source = this;
return new Enumerable(function () { var enumerator; var index = 0; var isSkipEnd = false;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { while (!isSkipEnd) { if (enumerator.moveNext()) { if (!predicate(enumerator.current(), index++)) { isSkipEnd = true; return this.yieldReturn(enumerator.current()); } continue; } else return false; }
return (enumerator.moveNext()) ? this.yieldReturn(enumerator.current()) : false;
}, function () { Utils.dispose(enumerator); }); });};
Enumerable.prototype.take = function (count) { var source = this;
return new Enumerable(function () { var enumerator; var index = 0;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { return (index++ < count && enumerator.moveNext()) ? this.yieldReturn(enumerator.current()) : false; }, function () { Utils.dispose(enumerator); } ); });};
// Overload:function(predicate<element>)// Overload:function(predicate<element,index>)Enumerable.prototype.takeWhile = function (predicate) { predicate = Utils.createLambda(predicate); var source = this;
return new Enumerable(function () { var enumerator; var index = 0;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { return (enumerator.moveNext() && predicate(enumerator.current(), index++)) ? this.yieldReturn(enumerator.current()) : false; }, function () { Utils.dispose(enumerator); }); });};
// Overload:function()// Overload:function(count)Enumerable.prototype.takeExceptLast = function (count) { if (count == null) count = 1; var source = this;
return new Enumerable(function () { if (count <= 0) return source.getEnumerator(); // do nothing
var enumerator; var q = [];
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { while (enumerator.moveNext()) { if (q.length == count) { q.push(enumerator.current()); return this.yieldReturn(q.shift()); } q.push(enumerator.current()); } return false; }, function () { Utils.dispose(enumerator); }); });};
Enumerable.prototype.takeFromLast = function (count) { if (count <= 0 || count == null) return Enumerable.empty(); var source = this;
return new Enumerable(function () { var sourceEnumerator; var enumerator; var q = [];
return new IEnumerator( function () { sourceEnumerator = source.getEnumerator(); }, function () { while (sourceEnumerator.moveNext()) { if (q.length == count) q.shift(); q.push(sourceEnumerator.current()); } if (enumerator == null) { enumerator = Enumerable.from(q).getEnumerator(); } return (enumerator.moveNext()) ? this.yieldReturn(enumerator.current()) : false; }, function () { Utils.dispose(enumerator); }); });};
// Overload:function(item)// Overload:function(predicate)Enumerable.prototype.indexOf = function (item) { var found = null;
// item as predicate if (typeof (item) === Types.Function) { this.forEach(function (x, i) { if (item(x, i)) { found = i; return false; } }); } else { this.forEach(function (x, i) { if (x === item) { found = i; return false; } }); }
return (found !== null) ? found : -1;};
// Overload:function(item)// Overload:function(predicate)Enumerable.prototype.lastIndexOf = function (item) { var result = -1;
// item as predicate if (typeof (item) === Types.Function) { this.forEach(function (x, i) { if (item(x, i)) result = i; }); } else { this.forEach(function (x, i) { if (x === item) result = i; }); }
return result;};
///////////////////// Convert Methods
Enumerable.prototype.cast = function () { return this;};
Enumerable.prototype.asEnumerable = function () { return Enumerable.from(this);};
Enumerable.prototype.toArray = function () { var array = []; this.forEach(function (x) { array.push(x); }); return array;};
// Overload:function(keySelector)// Overload:function(keySelector, elementSelector)// Overload:function(keySelector, elementSelector, compareSelector)Enumerable.prototype.toLookup = function (keySelector, elementSelector, compareSelector) { keySelector = Utils.createLambda(keySelector); elementSelector = Utils.createLambda(elementSelector); compareSelector = Utils.createLambda(compareSelector);
var dict = new Dictionary(compareSelector); this.forEach(function (x) { var key = keySelector(x); var element = elementSelector(x);
var array = dict.get(key); if (array !== undefined) array.push(element); else dict.add(key, [element]); }); return new Lookup(dict);};
Enumerable.prototype.toObject = function (keySelector, elementSelector) { keySelector = Utils.createLambda(keySelector); elementSelector = Utils.createLambda(elementSelector);
var obj = {}; this.forEach(function (x) { obj[keySelector(x)] = elementSelector(x); }); return obj;};
// Overload:function(keySelector, elementSelector)// Overload:function(keySelector, elementSelector, compareSelector)Enumerable.prototype.toDictionary = function (keySelector, elementSelector, compareSelector) { keySelector = Utils.createLambda(keySelector); elementSelector = Utils.createLambda(elementSelector); compareSelector = Utils.createLambda(compareSelector);
var dict = new Dictionary(compareSelector); this.forEach(function (x) { dict.add(keySelector(x), elementSelector(x)); }); return dict;};
// Overload:function()// Overload:function(replacer)// Overload:function(replacer, space)Enumerable.prototype.toJSONString = function (replacer, space) { if (typeof JSON === Types.Undefined || JSON.stringify == null) { throw new Error("toJSONString can't find JSON.stringify. This works native JSON support Browser or include json2.js"); } return JSON.stringify(this.toArray(), replacer, space);};
// Overload:function()// Overload:function(separator)// Overload:function(separator,selector)Enumerable.prototype.toJoinedString = function (separator, selector) { if (separator == null) separator = ""; if (selector == null) selector = Functions.Identity;
return this.select(selector).toArray().join(separator);};
//////////////////// Action Methods
// Overload:function(action<element>)// Overload:function(action<element,index>)Enumerable.prototype.doAction = function (action) { var source = this; action = Utils.createLambda(action);
return new Enumerable(function () { var enumerator; var index = 0;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { if (enumerator.moveNext()) { action(enumerator.current(), index++); return this.yieldReturn(enumerator.current()); } return false; }, function () { Utils.dispose(enumerator); }); });};
// Overload:function(action<element>)// Overload:function(action<element,index>)// Overload:function(func<element,bool>)// Overload:function(func<element,index,bool>)Enumerable.prototype.forEach = function (action) { action = Utils.createLambda(action);
var index = 0; var enumerator = this.getEnumerator(); try { while (enumerator.moveNext()) { if (action(enumerator.current(), index++) === false) break; } } finally { Utils.dispose(enumerator); }};
Enumerable.prototype.force = function () { var enumerator = this.getEnumerator();
try { while (enumerator.moveNext()) { } } finally { Utils.dispose(enumerator); }};
//////////////////////// Functional Methods
Enumerable.prototype.letBind = function (func) { func = Utils.createLambda(func); var source = this;
return new Enumerable(function () { var enumerator;
return new IEnumerator( function () { enumerator = Enumerable.from(func(source)).getEnumerator(); }, function () { return (enumerator.moveNext()) ? this.yieldReturn(enumerator.current()) : false; }, function () { Utils.dispose(enumerator); }); });};
Enumerable.prototype.share = function () { var source = this; var sharedEnumerator; var disposed = false;
return new DisposableEnumerable(function () { return new IEnumerator( function () { if (sharedEnumerator == null) { sharedEnumerator = source.getEnumerator(); } }, function () { if (disposed) throw new Error("enumerator is disposed");
return (sharedEnumerator.moveNext()) ? this.yieldReturn(sharedEnumerator.current()) : false; }, Functions.Blank ); }, function () { disposed = true; Utils.dispose(sharedEnumerator); });};
Enumerable.prototype.memoize = function () { var source = this; var cache; var enumerator; var disposed = false;
return new DisposableEnumerable(function () { var index = -1;
return new IEnumerator( function () { if (enumerator == null) { enumerator = source.getEnumerator(); cache = []; } }, function () { if (disposed) throw new Error("enumerator is disposed");
index++; if (cache.length <= index) { return (enumerator.moveNext()) ? this.yieldReturn(cache[index] = enumerator.current()) : false; }
return this.yieldReturn(cache[index]); }, Functions.Blank ); }, function () { disposed = true; Utils.dispose(enumerator); cache = null; });};
// Iterator support (ES6 for..of)if (Utils.hasNativeIteratorSupport()) { Enumerable.prototype[Symbol.iterator] = function () { return { enumerator: this.getEnumerator(), next: function () { if (this.enumerator.moveNext()) { return { done: false, value: this.enumerator.current() }; } else { return { done: true }; } } }; };}
//////////////////////////// Error Handling Methods
Enumerable.prototype.catchError = function (handler) { handler = Utils.createLambda(handler); var source = this;
return new Enumerable(function () { var enumerator;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { try { return (enumerator.moveNext()) ? this.yieldReturn(enumerator.current()) : false; } catch (e) { handler(e); return false; } }, function () { Utils.dispose(enumerator); }); });};
Enumerable.prototype.finallyAction = function (finallyAction) { finallyAction = Utils.createLambda(finallyAction); var source = this;
return new Enumerable(function () { var enumerator;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { return (enumerator.moveNext()) ? this.yieldReturn(enumerator.current()) : false; }, function () { try { Utils.dispose(enumerator); } finally { finallyAction(); } }); });};
/////////////////// Debug Methods
// Overload:function()// Overload:function(selector)Enumerable.prototype.log = function (selector) { selector = Utils.createLambda(selector);
return this.doAction(function (item) { if (typeof console !== Types.Undefined) { console.log(selector(item)); } });};
// Overload:function()// Overload:function(message)// Overload:function(message,selector)Enumerable.prototype.trace = function (message, selector) { if (message == null) message = "Trace"; selector = Utils.createLambda(selector);
return this.doAction(function (item) { if (typeof console !== Types.Undefined) { console.log(message, selector(item)); } });};
///////////// Private
var OrderedEnumerable = function (source, keySelector, comparer, descending, parent) { this.source = source; this.keySelector = Utils.createLambda(keySelector); this.descending = descending; this.parent = parent;
if (comparer) this.comparer = Utils.createLambda(comparer);};OrderedEnumerable.prototype = new Enumerable();
OrderedEnumerable.prototype.createOrderedEnumerable = function (keySelector, comparer, descending) { return new OrderedEnumerable(this.source, keySelector, comparer, descending, this);};
OrderedEnumerable.prototype.thenBy = function (keySelector, comparer) { return this.createOrderedEnumerable(keySelector, comparer, false);};
OrderedEnumerable.prototype.thenByDescending = function (keySelector, comparer) { return this.createOrderedEnumerable(keySelector, comparer, true);};
OrderedEnumerable.prototype.getEnumerator = function () { var self = this; var buffer; var indexes; var index = 0;
return new IEnumerator( function () { buffer = []; indexes = []; self.source.forEach(function (item, index) { buffer.push(item); indexes.push(index); }); var sortContext = SortContext.create(self, null); sortContext.GenerateKeys(buffer);
indexes.sort(function (a, b) { return sortContext.compare(a, b); }); }, function () { return (index < indexes.length) ? this.yieldReturn(buffer[indexes[index++]]) : false; }, Functions.Blank );};
var SortContext = function (keySelector, comparer, descending, child) { this.keySelector = keySelector; this.descending = descending; this.child = child; this.comparer = comparer; this.keys = null;};
SortContext.create = function (orderedEnumerable, currentContext) { var context = new SortContext( orderedEnumerable.keySelector, orderedEnumerable.comparer, orderedEnumerable.descending, currentContext );
if (orderedEnumerable.parent != null) return SortContext.create(orderedEnumerable.parent, context); return context;};
SortContext.prototype.GenerateKeys = function (source) { var len = source.length; var keySelector = this.keySelector; var keys = new Array(len); for (let i = 0; i < len; i++) keys[i] = keySelector(source[i]); this.keys = keys;
if (this.child != null) this.child.GenerateKeys(source);};
SortContext.prototype.compare = function (index1, index2) { var comparison = this.comparer ? this.comparer(this.keys[index1], this.keys[index2]) : Utils.compare(this.keys[index1], this.keys[index2]);
if (comparison == 0) { if (this.child != null) return this.child.compare(index1, index2); return Utils.compare(index1, index2); }
return (this.descending) ? -comparison : comparison;};
var DisposableEnumerable = function (getEnumerator, dispose) { this.dispose = dispose; Enumerable.call(this, getEnumerator);};DisposableEnumerable.prototype = new Enumerable();
var ArrayEnumerable = function (source) { this.getSource = function () { return source; };};ArrayEnumerable.prototype = new Enumerable();
ArrayEnumerable.prototype.any = function (predicate) { return (predicate == null) ? (this.getSource().length > 0) : Enumerable.prototype.any.apply(this, arguments);};
ArrayEnumerable.prototype.count = function (predicate) { return (predicate == null) ? this.getSource().length : Enumerable.prototype.count.apply(this, arguments);};
ArrayEnumerable.prototype.elementAt = function (index) { var source = this.getSource(); return (0 <= index && index < source.length) ? source[index] : Enumerable.prototype.elementAt.apply(this, arguments);};
ArrayEnumerable.prototype.elementAtOrDefault = function (index, defaultValue) { if (defaultValue === undefined) defaultValue = null; var source = this.getSource(); return (0 <= index && index < source.length) ? source[index] : defaultValue;};
ArrayEnumerable.prototype.first = function (predicate) { var source = this.getSource(); return (predicate == null && source.length > 0) ? source[0] : Enumerable.prototype.first.apply(this, arguments);};
ArrayEnumerable.prototype.firstOrDefault = function (predicate, defaultValue) { if (predicate !== undefined) { return Enumerable.prototype.firstOrDefault.apply(this, arguments); } defaultValue = predicate;
var source = this.getSource(); return source.length > 0 ? source[0] : defaultValue;};
ArrayEnumerable.prototype.last = function (predicate) { var source = this.getSource(); return (predicate == null && source.length > 0) ? source[source.length - 1] : Enumerable.prototype.last.apply(this, arguments);};
ArrayEnumerable.prototype.lastOrDefault = function (predicate, defaultValue) { if (predicate !== undefined) { return Enumerable.prototype.lastOrDefault.apply(this, arguments); } defaultValue = predicate;
var source = this.getSource(); return source.length > 0 ? source[source.length - 1] : defaultValue;};
ArrayEnumerable.prototype.skip = function (count) { var source = this.getSource();
return new Enumerable(function () { var index;
return new IEnumerator( function () { index = (count < 0) ? 0 : count; }, function () { return (index < source.length) ? this.yieldReturn(source[index++]) : false; }, Functions.Blank); });};
ArrayEnumerable.prototype.takeExceptLast = function (count) { if (count == null) count = 1; return this.take(this.getSource().length - count);};
ArrayEnumerable.prototype.takeFromLast = function (count) { return this.skip(this.getSource().length - count);};
ArrayEnumerable.prototype.reverse = function () { var source = this.getSource();
return new Enumerable(function () { var index;
return new IEnumerator( function () { index = source.length; }, function () { return (index > 0) ? this.yieldReturn(source[--index]) : false; }, Functions.Blank); });};
ArrayEnumerable.prototype.sequenceEqual = function (second, compareSelector) { if ((second instanceof ArrayEnumerable || second instanceof Array) && compareSelector == null && Enumerable.from(second).count() != this.count()) { return false; }
return Enumerable.prototype.sequenceEqual.apply(this, arguments);};
ArrayEnumerable.prototype.toJoinedString = function (separator, selector) { var source = this.getSource(); if (selector != null || !(source instanceof Array)) { return Enumerable.prototype.toJoinedString.apply(this, arguments); }
if (separator == null) separator = ""; return source.join(separator);};
ArrayEnumerable.prototype.getEnumerator = function () { var source = this.getSource(); var index = -1;
// fast and simple enumerator return { current: function () { return source[index]; }, moveNext: function () { return ++index < source.length; }, dispose: Functions.Blank };};
// optimization for multiple where and multiple select and whereselect
var WhereEnumerable = function (source, predicate) { this.prevSource = source; this.prevPredicate = predicate; // predicate.length always <= 1};WhereEnumerable.prototype = new Enumerable();
WhereEnumerable.prototype.where = function (predicate) { predicate = Utils.createLambda(predicate);
if (predicate.length <= 1) { const prevPredicate = this.prevPredicate; const composedPredicate = function (x) { return prevPredicate(x) && predicate(x); }; return new WhereEnumerable(this.prevSource, composedPredicate); } else { // if predicate use index, can't compose return Enumerable.prototype.where.call(this, predicate); }};
WhereEnumerable.prototype.select = function (selector) { selector = Utils.createLambda(selector);
return (selector.length <= 1) ? new WhereSelectEnumerable(this.prevSource, this.prevPredicate, selector) : Enumerable.prototype.select.call(this, selector);};
WhereEnumerable.prototype.getEnumerator = function () { var predicate = this.prevPredicate; var source = this.prevSource; var enumerator;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { while (enumerator.moveNext()) { if (predicate(enumerator.current())) { return this.yieldReturn(enumerator.current()); } } return false; }, function () { Utils.dispose(enumerator); });};
var WhereSelectEnumerable = function (source, predicate, selector) { this.prevSource = source; this.prevPredicate = predicate; // predicate.length always <= 1 or null this.prevSelector = selector; // selector.length always <= 1};WhereSelectEnumerable.prototype = new Enumerable();
WhereSelectEnumerable.prototype.where = function (predicate) { predicate = Utils.createLambda(predicate);
return (predicate.length <= 1) ? new WhereEnumerable(this, predicate) : Enumerable.prototype.where.call(this, predicate);};
WhereSelectEnumerable.prototype.select = function (selector) { selector = Utils.createLambda(selector);
if (selector.length <= 1) { const prevSelector = this.prevSelector; const composedSelector = function (x) { return selector(prevSelector(x)); }; return new WhereSelectEnumerable(this.prevSource, this.prevPredicate, composedSelector); } else { // if selector uses index, can't compose return Enumerable.prototype.select.call(this, selector); }};
WhereSelectEnumerable.prototype.getEnumerator = function () { var predicate = this.prevPredicate; var selector = this.prevSelector; var source = this.prevSource; var enumerator;
return new IEnumerator( function () { enumerator = source.getEnumerator(); }, function () { while (enumerator.moveNext()) { if (predicate == null || predicate(enumerator.current())) { return this.yieldReturn(selector(enumerator.current())); } } return false; }, function () { Utils.dispose(enumerator); });};
///////////////// Collections
var Dictionary = (function () { // static utility methods var callHasOwnProperty = function (target, key) { return Object.prototype.hasOwnProperty.call(target, key); };
var computeHashCode = function (obj) { if (obj === null) return "null"; if (obj === undefined) return "undefined";
return (typeof obj.toString === Types.Function) ? obj.toString() : Object.prototype.toString.call(obj); };
// LinkedList for Dictionary var HashEntry = function (key, value) { this.key = key; this.value = value; this.prev = null; this.next = null; };
var EntryList = function () { this.first = null; this.last = null; }; EntryList.prototype = { addLast: function (entry) { if (this.last != null) { this.last.next = entry; entry.prev = this.last; this.last = entry; } else this.first = this.last = entry; },
replace: function (entry, newEntry) { if (entry.prev != null) { entry.prev.next = newEntry; newEntry.prev = entry.prev; } else this.first = newEntry;
if (entry.next != null) { entry.next.prev = newEntry; newEntry.next = entry.next; } else this.last = newEntry;
},
remove: function (entry) { if (entry.prev != null) entry.prev.next = entry.next; else this.first = entry.next;
if (entry.next != null) entry.next.prev = entry.prev; else this.last = entry.prev; } };
// Overload:function() // Overload:function(compareSelector) var Dictionary = function (compareSelector) { this.countField = 0; this.entryList = new EntryList(); this.buckets = {}; // as Dictionary<string,List<object>> this.compareSelector = (compareSelector == null) ? Functions.Identity : compareSelector; }; Dictionary.prototype = { add: function (key, value) { var compareKey = this.compareSelector(key); var hash = computeHashCode(compareKey); var entry = new HashEntry(key, value); if (callHasOwnProperty(this.buckets, hash)) { const array = this.buckets[hash]; for (let i = 0; i < array.length; i++) { if (this.compareSelector(array[i].key) === compareKey) { this.entryList.replace(array[i], entry); array[i] = entry; return; } } array.push(entry); } else { this.buckets[hash] = [entry]; } this.countField++; this.entryList.addLast(entry); },
get: function (key) { var compareKey = this.compareSelector(key); var hash = computeHashCode(compareKey); if (!callHasOwnProperty(this.buckets, hash)) return undefined;
var array = this.buckets[hash]; for (let i = 0; i < array.length; i++) { const entry = array[i]; if (this.compareSelector(entry.key) === compareKey) return entry.value; } return undefined; },
set: function (key, value) { var compareKey = this.compareSelector(key); var hash = computeHashCode(compareKey); if (callHasOwnProperty(this.buckets, hash)) { const array = this.buckets[hash]; for (let i = 0; i < array.length; i++) { if (this.compareSelector(array[i].key) === compareKey) { const newEntry = new HashEntry(key, value); this.entryList.replace(array[i], newEntry); array[i] = newEntry; return true; } } } return false; },
contains: function (key) { var compareKey = this.compareSelector(key); var hash = computeHashCode(compareKey); if (!callHasOwnProperty(this.buckets, hash)) return false;
var array = this.buckets[hash]; for (let i = 0; i < array.length; i++) { if (this.compareSelector(array[i].key) === compareKey) return true; } return false; },
clear: function () { this.countField = 0; this.buckets = {}; this.entryList = new EntryList(); },
remove: function (key) { var compareKey = this.compareSelector(key); var hash = computeHashCode(compareKey); if (!callHasOwnProperty(this.buckets, hash)) return;
var array = this.buckets[hash]; for (let i = 0; i < array.length; i++) { if (this.compareSelector(array[i].key) === compareKey) { this.entryList.remove(array[i]); array.splice(i, 1); if (array.length == 0) delete this.buckets[hash]; this.countField--; return; } } },
count: function () { return this.countField; },
toEnumerable: function () { var self = this; return new Enumerable(function () { var currentEntry;
return new IEnumerator( function () { currentEntry = self.entryList.first; }, function () { if (currentEntry != null) { const result = { key: currentEntry.key, value: currentEntry.value }; currentEntry = currentEntry.next; return this.yieldReturn(result); } return false; }, Functions.Blank); }); } };
return Dictionary;})();
// dictionary = Dictionary<TKey, TValue[]>var Lookup = function (dictionary) { this.count = function () { return dictionary.count(); }; this.get = function (key) { return Enumerable.from(dictionary.get(key)); }; this.contains = function (key) { return dictionary.contains(key); }; this.toEnumerable = function () { return dictionary.toEnumerable().select(function (kvp) { return new Grouping(kvp.key, kvp.value); }); };};
var Grouping = function (groupKey, elements) { this.key = function () { return groupKey; }; ArrayEnumerable.call(this, elements);};Grouping.prototype = new ArrayEnumerable();
export default Enumerable;