123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733 |
- /*--------------------------------------------------------------------------
- * linq.js - LINQ for JavaScript
- * ver 2.2.0.2 (Jan. 21th, 2011)
- *
- * created and maintained by neuecc <ils@neue.cc>
- * licensed under Microsoft Public License(Ms-PL)
- * http://neue.cc/
- * http://linqjs.codeplex.com/
- *--------------------------------------------------------------------------*/
- Enumerable = (function ()
- {
- var Enumerable = function (getEnumerator)
- {
- this.GetEnumerator = getEnumerator;
- }
- // Generator
- Enumerable.Choice = function () // variable argument
- {
- var args = (arguments[0] instanceof Array) ? arguments[0] : arguments;
- return new Enumerable(function ()
- {
- return new IEnumerator(
- Functions.Blank,
- function ()
- {
- return this.Yield(args[Math.floor(Math.random() * args.length)]);
- },
- Functions.Blank);
- });
- }
- Enumerable.Cycle = function () // variable argument
- {
- var args = (arguments[0] instanceof Array) ? arguments[0] : arguments;
- return new Enumerable(function ()
- {
- var index = 0;
- return new IEnumerator(
- Functions.Blank,
- function ()
- {
- if (index >= args.length) index = 0;
- return this.Yield(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.Yield(obj.charAt(index++)) : false;
- },
- Functions.Blank);
- });
- }
- if (typeof obj != Types.Function)
- {
- // array or array like object
- if (typeof obj.length == Types.Number)
- {
- return new ArrayEnumerable(obj);
- }
- // JScript's IEnumerable
- if (!(obj instanceof Object) && Utils.IsIEnumerable(obj))
- {
- return new Enumerable(function ()
- {
- var isFirst = true;
- var enumerator;
- return new IEnumerator(
- function () { enumerator = new Enumerator(obj); },
- function ()
- {
- if (isFirst) isFirst = false;
- else enumerator.moveNext();
- return (enumerator.atEnd()) ? false : this.Yield(enumerator.item());
- },
- Functions.Blank);
- });
- }
- }
- // case function/object : Create KeyValuePair[]
- return new Enumerable(function ()
- {
- var array = [];
- var index = 0;
- return new IEnumerator(
- function ()
- {
- for (var key in obj)
- {
- if (!(obj[key] instanceof Function))
- {
- array.push({ Key: key, Value: obj[key] });
- }
- }
- },
- function ()
- {
- return (index < array.length)
- ? this.Yield(array[index++])
- : false;
- },
- Functions.Blank);
- });
- },
- Enumerable.Return = 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.Yield(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 Enumerable.ToInfinity(start, step).Take(count);
- }
- // Overload:function(start, count)
- // Overload:function(start, count, step)
- Enumerable.RangeDown = function (start, count, step)
- {
- if (step == null) step = 1;
- return Enumerable.ToNegativeInfinity(start, step).Take(count);
- }
- // Overload:function(start, to)
- // Overload:function(start, to, step)
- Enumerable.RangeTo = function (start, to, step)
- {
- if (step == null) step = 1;
- return (start < to)
- ? Enumerable.ToInfinity(start, step).TakeWhile(function (i) { return i <= to; })
- : Enumerable.ToNegativeInfinity(start, step).TakeWhile(function (i) { return i >= to; })
- }
- // Overload:function(obj)
- // Overload:function(obj, num)
- Enumerable.Repeat = function (obj, num)
- {
- if (num != null) return Enumerable.Repeat(obj).Take(num);
- return new Enumerable(function ()
- {
- return new IEnumerator(
- Functions.Blank,
- function () { return this.Yield(obj); },
- 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.Yield(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.Yield(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.Yield(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.Yield(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.Yield(value);
- }
- value = func(value);
- return this.Yield(value);
- },
- Functions.Blank);
- });
- }
- // Extension Methods
- Enumerable.prototype =
- {
- /* Projection and Filtering Methods */
- // Overload:function(func)
- // Overload:function(func, resultSelector<element>)
- // Overload:function(func, resultSelector<element, nestLevel>)
- CascadeBreadthFirst: 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.Yield(resultSelector(enumerator.Current(), nestLevel));
- }
- var 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>)
- CascadeDepthFirst: 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())
- {
- var value = resultSelector(enumerator.Current(), enumeratorStack.length);
- enumeratorStack.push(enumerator);
- enumerator = Enumerable.From(func(enumerator.Current())).GetEnumerator();
- return this.Yield(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(); }) }
- });
- });
- },
- 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.Yield(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.Yield(enumerator.Current());
- }
- }
- return false;
- }
- },
- function ()
- {
- try { Utils.Dispose(enumerator); }
- finally { Utils.Dispose(middleEnumerator); }
- });
- });
- },
- 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.Yield(selector(prev, enumerator.Current()))
- : false;
- },
- function () { Utils.Dispose(enumerator); });
- });
- },
- // Overload:function(func)
- // Overload:function(seed,func<value,element>)
- // Overload:function(seed,func<value,element>,resultSelector)
- Scan: function (seed, func, resultSelector)
- {
- if (resultSelector != null) return this.Scan(seed, func).Select(resultSelector);
- var isUseSeed;
- if (func == null)
- {
- func = Utils.CreateLambda(seed); // arguments[0]
- 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.Yield(value = enumerator.Current());
- }
- }
- else
- {
- return this.Yield(value = seed);
- }
- }
- return (enumerator.MoveNext())
- ? this.Yield(value = func(value, enumerator.Current()))
- : false;
- },
- function () { Utils.Dispose(enumerator); });
- });
- },
- // Overload:function(selector<element>)
- // Overload:function(selector<element,index>)
- Select: function (selector)
- {
- var source = this;
- selector = Utils.CreateLambda(selector);
- return new Enumerable(function ()
- {
- var enumerator;
- var index = 0;
- return new IEnumerator(
- function () { enumerator = source.GetEnumerator(); },
- function ()
- {
- return (enumerator.MoveNext())
- ? this.Yield(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)
- 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)
- {
- var middleSeq = collectionSelector(enumerator.Current(), index++);
- middleEnumerator = Enumerable.From(middleSeq).GetEnumerator();
- }
- if (middleEnumerator.MoveNext())
- {
- return this.Yield(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>)
- Where: 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 ()
- {
- while (enumerator.MoveNext())
- {
- if (predicate(enumerator.Current(), index++))
- {
- return this.Yield(enumerator.Current());
- }
- }
- return false;
- },
- function () { Utils.Dispose(enumerator); })
- });
- },
- 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 });
- },
- // Overload:function(second,selector<outer,inner>)
- // Overload:function(second,selector<outer,inner,index>)
- Zip: function (second, selector)
- {
- selector = Utils.CreateLambda(selector);
- var source = this;
- 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.Yield(selector(firstEnumerator.Current(), secondEnumerator.Current(), index++));
- }
- return false;
- },
- function ()
- {
- try { Utils.Dispose(firstEnumerator); }
- finally { Utils.Dispose(secondEnumerator); }
- })
- });
- },
- /* Join Methods */
- // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector)
- // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector)
- 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)
- {
- var innerElement = innerElements[innerCount++];
- if (innerElement !== undefined)
- {
- return this.Yield(resultSelector(outerEnumerator.Current(), innerElement));
- }
- innerElement = null;
- innerCount = 0;
- }
- if (outerEnumerator.MoveNext())
- {
- var 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)
- 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())
- {
- var innerElement = lookup.Get(outerKeySelector(enumerator.Current()));
- return this.Yield(resultSelector(enumerator.Current(), innerElement));
- }
- return false;
- },
- function () { Utils.Dispose(enumerator); })
- });
- },
- /* Set Methods */
- 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)
- 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); }
- },
- Concat: function (second)
- {
- var source = this;
- return new Enumerable(function ()
- {
- var firstEnumerator;
- var secondEnumerator;
- return new IEnumerator(
- function () { firstEnumerator = source.GetEnumerator(); },
- function ()
- {
- if (secondEnumerator == null)
- {
- if (firstEnumerator.MoveNext()) return this.Yield(firstEnumerator.Current());
- secondEnumerator = Enumerable.From(second).GetEnumerator();
- }
- if (secondEnumerator.MoveNext()) return this.Yield(secondEnumerator.Current());
- return false;
- },
- function ()
- {
- try { Utils.Dispose(firstEnumerator); }
- finally { Utils.Dispose(secondEnumerator); }
- })
- });
- },
- 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.Yield(secondEnumerator.Current());
- }
- if (firstEnumerator.MoveNext())
- {
- count++;
- return this.Yield(firstEnumerator.Current());
- }
- if (!isEnumerated && secondEnumerator.MoveNext())
- {
- return this.Yield(secondEnumerator.Current());
- }
- return false;
- },
- function ()
- {
- try { Utils.Dispose(firstEnumerator); }
- finally { Utils.Dispose(secondEnumerator); }
- })
- });
- },
- Alternate: function (value)
- {
- value = Enumerable.Return(value);
- return this.SelectMany(function (elem)
- {
- return Enumerable.Return(elem).Concat(value);
- }).TakeExceptLast();
- },
- // Overload:function(value)
- // Overload:function(value, compareSelector)
- 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) }
- },
- DefaultIfEmpty: function (defaultValue)
- {
- var source = this;
- return new Enumerable(function ()
- {
- var enumerator;
- var isFirst = true;
- return new IEnumerator(
- function () { enumerator = source.GetEnumerator(); },
- function ()
- {
- if (enumerator.MoveNext())
- {
- isFirst = false;
- return this.Yield(enumerator.Current());
- }
- else if (isFirst)
- {
- isFirst = false;
- return this.Yield(defaultValue);
- }
- return false;
- },
- function () { Utils.Dispose(enumerator); })
- });
- },
- // Overload:function()
- // Overload:function(compareSelector)
- Distinct: function (compareSelector)
- {
- return this.Except(Enumerable.Empty(), compareSelector);
- },
- // Overload:function(second)
- // Overload:function(second, compareSelector)
- 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())
- {
- var current = enumerator.Current();
- if (!keys.Contains(current))
- {
- keys.Add(current);
- return this.Yield(current);
- }
- }
- return false;
- },
- function () { Utils.Dispose(enumerator); })
- });
- },
- // Overload:function(second)
- // Overload:function(second, compareSelector)
- 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())
- {
- var current = enumerator.Current();
- if (!outs.Contains(current) && keys.Contains(current))
- {
- outs.Add(current);
- return this.Yield(current);
- }
- }
- return false;
- },
- function () { Utils.Dispose(enumerator); })
- });
- },
- // Overload:function(second)
- // Overload:function(second, compareSelector)
- SequenceEqual: function (second, compareSelector)
- {
- compareSelector = Utils.CreateLambda(compareSelector);
- var firstEnumerator = this.GetEnumerator();
- try
- {
- var 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); }
- },
- 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.Yield(current);
- }
- }
- secondEnumerator = Enumerable.From(second).GetEnumerator();
- }
- while (secondEnumerator.MoveNext())
- {
- current = secondEnumerator.Current();
- if (!keys.Contains(current))
- {
- keys.Add(current);
- return this.Yield(current);
- }
- }
- return false;
- },
- function ()
- {
- try { Utils.Dispose(firstEnumerator); }
- finally { Utils.Dispose(secondEnumerator); }
- })
- });
- },
- /* Ordering Methods */
- OrderBy: function (keySelector)
- {
- return new OrderedEnumerable(this, keySelector, false);
- },
- OrderByDescending: function (keySelector)
- {
- return new OrderedEnumerable(this, keySelector, true);
- },
- 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.Yield(buffer[--index])
- : false;
- },
- Functions.Blank)
- });
- },
- Shuffle: function ()
- {
- var source = this;
- return new Enumerable(function ()
- {
- var buffer;
- return new IEnumerator(
- function () { buffer = source.ToArray(); },
- function ()
- {
- if (buffer.length > 0)
- {
- var i = Math.floor(Math.random() * buffer.length);
- return this.Yield(buffer.splice(i, 1)[0]);
- }
- return false;
- },
- Functions.Blank)
- });
- },
- /* Grouping Methods */
- // Overload:function(keySelector)
- // Overload:function(keySelector,elementSelector)
- // Overload:function(keySelector,elementSelector,resultSelector)
- // Overload:function(keySelector,elementSelector,resultSelector,compareSelector)
- 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.Yield(enumerator.Current())
- : this.Yield(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)
- 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)
- {
- var 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.Yield(result);
- }
- return false;
- },
- function () { Utils.Dispose(enumerator); })
- });
- },
- BufferWithCount: 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.Yield(array);
- }
- if (array.length > 0) return this.Yield(array);
- return false;
- },
- function () { Utils.Dispose(enumerator); })
- });
- },
- /* Aggregate Methods */
- // Overload:function(func)
- // Overload:function(seed,func)
- // Overload:function(seed,func,resultSelector)
- Aggregate: function (seed, func, resultSelector)
- {
- return this.Scan(seed, func, resultSelector).Last();
- },
- // Overload:function()
- // Overload:function(selector)
- 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)
- 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)
- 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)
- Min: function (selector)
- {
- if (selector == null) selector = Functions.Identity;
- return this.Select(selector).Aggregate(function (a, b) { return (a < b) ? a : b; });
- },
- MaxBy: function (keySelector)
- {
- keySelector = Utils.CreateLambda(keySelector);
- return this.Aggregate(function (a, b) { return (keySelector(a) > keySelector(b)) ? a : b });
- },
- 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)
- Sum: function (selector)
- {
- if (selector == null) selector = Functions.Identity;
- return this.Select(selector).Aggregate(0, function (a, b) { return a + b; });
- },
- /* Paging Methods */
- 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;
- },
- ElementAtOrDefault: function (index, defaultValue)
- {
- 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)
- 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;
- },
- // Overload:function(defaultValue)
- // Overload:function(defaultValue,predicate)
- FirstOrDefault: function (defaultValue, predicate)
- {
- if (predicate != null) return this.Where(predicate).FirstOrDefault(defaultValue);
- var value;
- var found = false;
- this.ForEach(function (x)
- {
- value = x;
- found = true;
- return false;
- });
- return (!found) ? defaultValue : value;
- },
- // Overload:function()
- // Overload:function(predicate)
- 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;
- },
- // Overload:function(defaultValue)
- // Overload:function(defaultValue,predicate)
- LastOrDefault: function (defaultValue, predicate)
- {
- if (predicate != null) return this.Where(predicate).LastOrDefault(defaultValue);
- var value;
- var found = false;
- this.ForEach(function (x)
- {
- found = true;
- value = x;
- });
- return (!found) ? defaultValue : value;
- },
- // Overload:function()
- // Overload:function(predicate)
- 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)
- SingleOrDefault: function (defaultValue, predicate)
- {
- if (predicate != null) return this.Where(predicate).SingleOrDefault(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;
- },
- 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.Yield(enumerator.Current())
- : false;
- },
- function () { Utils.Dispose(enumerator); })
- });
- },
- // Overload:function(predicate<element>)
- // Overload:function(predicate<element,index>)
- 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.Yield(enumerator.Current());
- }
- continue;
- }
- else return false;
- }
- return (enumerator.MoveNext())
- ? this.Yield(enumerator.Current())
- : false;
- },
- function () { Utils.Dispose(enumerator); });
- });
- },
- 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.Yield(enumerator.Current())
- : false;
- },
- function () { Utils.Dispose(enumerator); }
- )
- });
- },
- // Overload:function(predicate<element>)
- // Overload:function(predicate<element,index>)
- 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.Yield(enumerator.Current())
- : false;
- },
- function () { Utils.Dispose(enumerator); });
- });
- },
- // Overload:function()
- // Overload:function(count)
- 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.Yield(q.shift());
- }
- q.push(enumerator.Current());
- }
- return false;
- },
- function () { Utils.Dispose(enumerator); });
- });
- },
- 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.Yield(enumerator.Current())
- : false;
- },
- function () { Utils.Dispose(enumerator); });
- });
- },
- IndexOf: function (item)
- {
- var found = null;
- this.ForEach(function (x, i)
- {
- if (x === item)
- {
- found = i;
- return true;
- }
- });
- return (found !== null) ? found : -1;
- },
- LastIndexOf: function (item)
- {
- var result = -1;
- this.ForEach(function (x, i)
- {
- if (x === item) result = i;
- });
- return result;
- },
- /* Convert Methods */
- 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)
- 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);
- },
- 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)
- 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)
- ToJSON: function (replacer, space)
- {
- return JSON.stringify(this.ToArray(), replacer, space);
- },
- // Overload:function()
- // Overload:function(separator)
- // Overload:function(separator,selector)
- ToString: 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>)
- Do: 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.Yield(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>)
- 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); }
- },
- // Overload:function()
- // Overload:function(separator)
- // Overload:function(separator,selector)
- Write: function (separator, selector)
- {
- if (separator == null) separator = "";
- selector = Utils.CreateLambda(selector);
- var isFirst = true;
- this.ForEach(function (item)
- {
- if (isFirst) isFirst = false;
- else document.write(separator);
- document.write(selector(item));
- });
- },
- // Overload:function()
- // Overload:function(selector)
- WriteLine: function (selector)
- {
- selector = Utils.CreateLambda(selector);
- this.ForEach(function (item)
- {
- document.write(selector(item));
- document.write("<br />");
- });
- },
- Force: function ()
- {
- var enumerator = this.GetEnumerator();
- try { while (enumerator.MoveNext()) { } }
- finally { Utils.Dispose(enumerator); }
- },
- /* Functional Methods */
- Let: 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.Yield(enumerator.Current())
- : false;
- },
- function () { Utils.Dispose(enumerator); })
- });
- },
- Share: function ()
- {
- var source = this;
- var sharedEnumerator;
- return new Enumerable(function ()
- {
- return new IEnumerator(
- function ()
- {
- if (sharedEnumerator == null)
- {
- sharedEnumerator = source.GetEnumerator();
- }
- },
- function ()
- {
- return (sharedEnumerator.MoveNext())
- ? this.Yield(sharedEnumerator.Current())
- : false;
- },
- Functions.Blank
- )
- });
- },
- MemoizeAll: function ()
- {
- var source = this;
- var cache;
- var enumerator;
- return new Enumerable(function ()
- {
- var index = -1;
- return new IEnumerator(
- function ()
- {
- if (enumerator == null)
- {
- enumerator = source.GetEnumerator();
- cache = [];
- }
- },
- function ()
- {
- index++;
- if (cache.length <= index)
- {
- return (enumerator.MoveNext())
- ? this.Yield(cache[index] = enumerator.Current())
- : false;
- }
- return this.Yield(cache[index]);
- },
- Functions.Blank
- )
- });
- },
- /* Error Handling Methods */
- Catch: 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.Yield(enumerator.Current())
- : false;
- }
- catch (e)
- {
- handler(e);
- return false;
- }
- },
- function () { Utils.Dispose(enumerator); });
- });
- },
- Finally: 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.Yield(enumerator.Current())
- : false;
- },
- function ()
- {
- try { Utils.Dispose(enumerator); }
- finally { finallyAction(); }
- });
- });
- },
- /* For Debug Methods */
- // Overload:function()
- // Overload:function(message)
- // Overload:function(message,selector)
- Trace: function (message, selector)
- {
- if (message == null) message = "Trace";
- selector = Utils.CreateLambda(selector);
- return this.Do(function (item)
- {
- console.log(message, ":", selector(item));
- });
- }
- }
- // private
- // static functions
- var Functions =
- {
- Identity: function (x) { return x; },
- True: function () { return true; },
- Blank: function () { }
- }
- // static const
- var Types =
- {
- Boolean: typeof true,
- Number: typeof 0,
- String: typeof "",
- Object: typeof {},
- Undefined: typeof undefined,
- Function: typeof function () { }
- }
- // static utility methods
- var Utils =
- {
- // Create anonymous function from lambda expression string
- CreateLambda: function (expression)
- {
- if (expression == null) return Functions.Identity;
- if (typeof expression == Types.String)
- {
- if (expression == "")
- {
- return Functions.Identity;
- }
- else if (expression.indexOf("=>") == -1)
- {
- return new Function("$,$$,$$$,$$$$", "return " + expression);
- }
- else
- {
- var expr = expression.match(/^[(\s]*([^()]*?)[)\s]*=>(.*)/);
- return new Function(expr[1], "return " + expr[2]);
- }
- }
- return expression;
- },
- IsIEnumerable: function (obj)
- {
- if (typeof Enumerator != Types.Undefined)
- {
- try
- {
- new Enumerator(obj);
- return true;
- }
- catch (e) { }
- }
- return false;
- },
- Compare: function (a, b)
- {
- return (a === b) ? 0
- : (a > b) ? 1
- : -1;
- },
- Dispose: function (obj)
- {
- if (obj != null) obj.Dispose();
- }
- }
- // IEnumerator State
- var State = { Before: 0, Running: 1, After: 2 }
- // name "Enumerator" is conflict JScript's "Enumerator"
- 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;
- }
- 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; }
- }
- }
- // for tryGetNext
- var Yielder = function ()
- {
- var current = null;
- this.Current = function () { return current; }
- this.Yield = function (value)
- {
- current = value;
- return true;
- }
- }
- // for OrderBy/ThenBy
- var OrderedEnumerable = function (source, keySelector, descending, parent)
- {
- this.source = source;
- this.keySelector = Utils.CreateLambda(keySelector);
- this.descending = descending;
- this.parent = parent;
- }
- OrderedEnumerable.prototype = new Enumerable();
- OrderedEnumerable.prototype.CreateOrderedEnumerable = function (keySelector, descending)
- {
- return new OrderedEnumerable(this.source, keySelector, descending, this);
- }
- OrderedEnumerable.prototype.ThenBy = function (keySelector)
- {
- return this.CreateOrderedEnumerable(keySelector, false);
- }
- OrderedEnumerable.prototype.ThenByDescending = function (keySelector)
- {
- return this.CreateOrderedEnumerable(keySelector, 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.Yield(buffer[indexes[index++]])
- : false;
- },
- Functions.Blank
- )
- }
- var SortContext = function (keySelector, descending, child)
- {
- this.keySelector = keySelector;
- this.descending = descending;
- this.child = child;
- this.keys = null;
- }
- SortContext.Create = function (orderedEnumerable, currentContext)
- {
- var context = new SortContext(orderedEnumerable.keySelector, 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 (var 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 = Utils.Compare(this.keys[index1], this.keys[index2]);
- if (comparison == 0)
- {
- if (this.child != null) return this.child.Compare(index1, index2)
- comparison = Utils.Compare(index1, index2);
- }
- return (this.descending) ? -comparison : comparison;
- }
- // optimize array or arraylike object
- var ArrayEnumerable = function (source)
- {
- this.source = source;
- }
- ArrayEnumerable.prototype = new Enumerable();
- ArrayEnumerable.prototype.Any = function (predicate)
- {
- return (predicate == null)
- ? (this.source.length > 0)
- : Enumerable.prototype.Any.apply(this, arguments);
- }
- ArrayEnumerable.prototype.Count = function (predicate)
- {
- return (predicate == null)
- ? this.source.length
- : Enumerable.prototype.Count.apply(this, arguments);
- }
- ArrayEnumerable.prototype.ElementAt = function (index)
- {
- return (0 <= index && index < this.source.length)
- ? this.source[index]
- : Enumerable.prototype.ElementAt.apply(this, arguments);
- }
- ArrayEnumerable.prototype.ElementAtOrDefault = function (index, defaultValue)
- {
- return (0 <= index && index < this.source.length)
- ? this.source[index]
- : defaultValue;
- }
- ArrayEnumerable.prototype.First = function (predicate)
- {
- return (predicate == null && this.source.length > 0)
- ? this.source[0]
- : Enumerable.prototype.First.apply(this, arguments);
- }
- ArrayEnumerable.prototype.FirstOrDefault = function (defaultValue, predicate)
- {
- if (predicate != null)
- {
- return Enumerable.prototype.FirstOrDefault.apply(this, arguments);
- }
- return this.source.length > 0 ? this.source[0] : defaultValue;
- }
- ArrayEnumerable.prototype.Last = function (predicate)
- {
- return (predicate == null && this.source.length > 0)
- ? this.source[this.source.length - 1]
- : Enumerable.prototype.Last.apply(this, arguments);
- }
- ArrayEnumerable.prototype.LastOrDefault = function (defaultValue, predicate)
- {
- if (predicate != null)
- {
- return Enumerable.prototype.LastOrDefault.apply(this, arguments);
- }
- return this.source.length > 0 ? this.source[this.source.length - 1] : defaultValue;
- }
- ArrayEnumerable.prototype.Skip = function (count)
- {
- var source = this.source;
- return new Enumerable(function ()
- {
- var index;
- return new IEnumerator(
- function () { index = (count < 0) ? 0 : count },
- function ()
- {
- return (index < source.length)
- ? this.Yield(source[index++])
- : false;
- },
- Functions.Blank);
- });
- };
- ArrayEnumerable.prototype.TakeExceptLast = function (count)
- {
- if (count == null) count = 1;
- return this.Take(this.source.length - count);
- }
- ArrayEnumerable.prototype.TakeFromLast = function (count)
- {
- return this.Skip(this.source.length - count);
- }
- ArrayEnumerable.prototype.Reverse = function ()
- {
- var source = this.source;
- return new Enumerable(function ()
- {
- var index;
- return new IEnumerator(
- function ()
- {
- index = source.length;
- },
- function ()
- {
- return (index > 0)
- ? this.Yield(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.ToString = function (separator, selector)
- {
- if (selector != null || !(this.source instanceof Array))
- {
- return Enumerable.prototype.ToString.apply(this, arguments);
- }
- if (separator == null) separator = "";
- return this.source.join(separator);
- }
- ArrayEnumerable.prototype.GetEnumerator = function ()
- {
- var source = this.source;
- var index = 0;
- return new IEnumerator(
- Functions.Blank,
- function ()
- {
- return (index < source.length)
- ? this.Yield(source[index++])
- : false;
- },
- Functions.Blank);
- }
- // Collections
- var Dictionary = (function ()
- {
- // static utility methods
- var HasOwnProperty = 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.count = 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 (HasOwnProperty(this.buckets, hash))
- {
- var array = this.buckets[hash];
- for (var 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.count++;
- this.entryList.AddLast(entry);
- },
- Get: function (key)
- {
- var compareKey = this.compareSelector(key);
- var hash = ComputeHashCode(compareKey);
- if (!HasOwnProperty(this.buckets, hash)) return undefined;
- var array = this.buckets[hash];
- for (var i = 0; i < array.length; i++)
- {
- var 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 (HasOwnProperty(this.buckets, hash))
- {
- var array = this.buckets[hash];
- for (var i = 0; i < array.length; i++)
- {
- if (this.compareSelector(array[i].Key) === compareKey)
- {
- var 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 (!HasOwnProperty(this.buckets, hash)) return false;
- var array = this.buckets[hash];
- for (var i = 0; i < array.length; i++)
- {
- if (this.compareSelector(array[i].Key) === compareKey) return true;
- }
- return false;
- },
- Clear: function ()
- {
- this.count = 0;
- this.buckets = {};
- this.entryList = new EntryList();
- },
- Remove: function (key)
- {
- var compareKey = this.compareSelector(key);
- var hash = ComputeHashCode(compareKey);
- if (!HasOwnProperty(this.buckets, hash)) return;
- var array = this.buckets[hash];
- for (var 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.count--;
- return;
- }
- }
- },
- Count: function ()
- {
- return this.count;
- },
- ToEnumerable: function ()
- {
- var self = this;
- return new Enumerable(function ()
- {
- var currentEntry;
- return new IEnumerator(
- function () { currentEntry = self.entryList.First },
- function ()
- {
- if (currentEntry != null)
- {
- var result = { Key: currentEntry.Key, Value: currentEntry.Value };
- currentEntry = currentEntry.Next;
- return this.Yield(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 (key, elements)
- {
- this.Key = function ()
- {
- return key;
- }
- ArrayEnumerable.call(this, elements);
- }
- Grouping.prototype = new ArrayEnumerable();
- // out to global
- return Enumerable;
- })()
|