linq 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67233bc3ad787b03aacc9e27ed2cc2eae58444a3
4
- data.tar.gz: 99f43e87ec3e84fe9e4179117317226f6b201864
3
+ metadata.gz: ac15f012b9305f37758b8b21340827d593637cfe
4
+ data.tar.gz: 3dbd640de40cee2ab964633ae7bca683d07578ea
5
5
  SHA512:
6
- metadata.gz: 0ada646d74a47364d6575e4ee65dd7fce85becc7ce587b9029e94826b9edfaadeab9121ec484a64facd7662572947243a4bc7335753012b148780c4a59fb1aca
7
- data.tar.gz: 3a245111d93398046230ca4714ae7abd0e9c08a7bb57ed10f2d52d64b946bcdc598d8830f1652cbc4f355f8286b5fa0a24c2c05f17a145825bd51914b6ef36d0
6
+ metadata.gz: 2f0820c0bc3857fe3aa12b77c120c460f0bc2e419268328c86637b52db8f3cc17c1312c4580dbf66ba64917fe3f6526599431c9c7b0e68d586019d766bfd11d6
7
+ data.tar.gz: a6074ca14f8ba775d0fc1baef7d3be13d0933521f212c1930560b8d465bcb53c829fac5e8be7002f596673e5a9caba44e21eeef094826cfa562ed0ea289c784e
data/README.md CHANGED
@@ -1,39 +1,103 @@
1
- # Linq
2
-
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/linq`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
6
-
7
- ## Installation
8
-
9
- Add this line to your application's Gemfile:
10
-
11
- ```ruby
12
- gem 'linq'
13
- ```
14
-
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install linq
22
-
23
- ## Usage
24
-
25
- TODO: Write usage instructions here
26
-
27
- ## Development
28
-
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
-
33
- ## Contributing
34
-
35
- 1. Fork it ( https://github.com/[my-github-username]/linq/fork )
36
- 2. Create your feature branch (`git checkout -b my-new-feature`)
37
- 3. Commit your changes (`git commit -am 'Add some feature'`)
38
- 4. Push to the branch (`git push origin my-new-feature`)
39
- 5. Create a new Pull Request
1
+ # Linq
2
+
3
+ Language-Integrated Query (LINQ) is a set of features introduced in Visual Studio 2008 (That moment for #C, VisualBasic) that extends powerful query capabilities to the language syntax. This gem is wrapper for linq.js JavaScript plugin. LINQ introduces standard, easily-learned patterns for querying and updating data, and the technology can be extended to support potentially any kind of data store.
4
+
5
+ ## Features
6
+
7
+ - Implement all .NET 4.0 methods and many extra methods (inspiration from Rx, Achiral, Haskell, Ruby, etc...)
8
+ - Complete lazy evaluation
9
+ - Two versions - linq.js and jquery.linq.js (jQuery plugin)
10
+ - Binding for Reactive Extensions for JavaScript(RxJS)
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'linq'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install linq
27
+
28
+ Add to javascript manifest `application.js`
29
+
30
+ //= require linq
31
+
32
+ ## Examples of usage
33
+ ```javascript
34
+ var jsonArray = [
35
+ { "user": { "id": 100, "screen_name": "d_linq" }, "text": "to objects" },
36
+ { "user": { "id": 130, "screen_name": "c_bill" }, "text": "g" },
37
+ { "user": { "id": 155, "screen_name": "b_mskk" }, "text": "kabushiki kaisha" },
38
+ { "user": { "id": 301, "screen_name": "a_xbox" }, "text": "halo reach" }
39
+ ]
40
+
41
+ var queryResult = Enumerable.From(jsonArray)
42
+ .Where(function (x) { return x.user.id < 200 })
43
+ .OrderBy(function (x) { return x.user.screen_name })
44
+ .Select(function (x) { return x.user.screen_name + ':' + x.text })
45
+ .ToArray();
46
+
47
+ // shortcut! string lambda selector
48
+ var queryResult2 = Enumerable.From(jsonArray)
49
+ .Where("$.user.id < 200")
50
+ .OrderBy("$.user.screen_name")
51
+ .Select("$.user.screen_name + ':' + $.text")
52
+ .ToArray();
53
+ ```
54
+
55
+ More tricky:
56
+
57
+ ```javascript
58
+ // anonymous function
59
+ Enumerable.Range(1, 10)
60
+ .Where(function(i) { return i % 3 == 0; })
61
+ .Select(function(i) { return i * 10; });
62
+
63
+ // lambda expression
64
+ Enumerable.Range(1, 10).Where("i => i % 3 == 0").Select("i => i * 10");
65
+
66
+ // $ is default iterator variable like Scala's "_" or Groovy's "it"
67
+ Enumerable.Range(1, 10).Where("$ % 3 == 0").Select("$ * 10");
68
+
69
+ // "" is shorthand of "x => x" (identity function)
70
+ Enumerable.Range(4, 7).Join(Enumerable.Range(8, 5), "", "", "outer,inner=>outer*inner");
71
+
72
+ // Enumerable.From is wrap from primitive array, string(to charArray), object(to KeyValuePair[]) etc..
73
+ var array = [100, 200, 30, 40, 500, 40, 200];
74
+ var ex1 = Enumerable.From(array).Distinct().ToArray(); // [100, 200, 30, 40, 500]
75
+ var ex2 = Enumerable.From("foobar").ToArray(); // ["f", "o", "o", "b", "a", "r"];
76
+ var ex3 = Enumerable.From({foo:10, bar:20}).ToArray(); // [{Key:"foo",Value:10}, {Key:"bar",Value:20}]
77
+
78
+ // object literal
79
+ Enumerable.From(array).Select("val,i=>{Value:val, Index:i}")
80
+ ```
81
+ And Jquery:
82
+
83
+ ```javascript
84
+ // $.Enumerable
85
+ $.Enumerable.Range(1, 10).Where("$ % 2 == 0").ForEach("alert($)");
86
+
87
+ // TojQuery - Enumerable to jQuery
88
+ $.Enumerable.Range(1, 10)
89
+ .Select(function (i) { return $("<option>").text(i)[0] })
90
+ .TojQuery()
91
+ .appendTo("#select1");
92
+
93
+ // toEnumerable - jQuery to Enumerable
94
+ var sum = $("#select1").children()
95
+ .toEnumerable()
96
+ .Select("parseInt($.text())")
97
+ .Sum(); // 55
98
+ ```
99
+
100
+
101
+ Full [documentation is on the wiki][wiki]
102
+
103
+ [wiki]: https://github.com/khusnetdinov/linq/wiki
@@ -0,0 +1,28 @@
1
+ // extension for jQuery
2
+
3
+ (function (root) {
4
+ if (root.Enumerable == null) {
5
+ throw new Error("can't find Enumerable. linq.jquery.js must load after linq.js");
6
+ }
7
+ if (root.jQuery == null) {
8
+ throw new Error("can't find jQuery. linq.jquery.js must load after jQuery");
9
+ }
10
+
11
+ var Enumerable = root.Enumerable;
12
+ var $ = root.jQuery;
13
+
14
+ $.fn.toEnumerable = function () {
15
+ /// <summary>each contains elements. to Enumerable&lt;jQuery&gt;.</summary>
16
+ return Enumerable.from(this).select(function (e) { return $(e) });
17
+ };
18
+
19
+ Enumerable.prototype.tojQuery = function () {
20
+ /// <summary>Enumerable to jQuery. All elements add to blank jQuery object.</summary>
21
+ return this.aggregate($(), function (j, x) { return j.add(x); });
22
+ };
23
+
24
+ Enumerable.prototype.tojQueryAsArray = function () {
25
+ /// <summary>Enumerable to jQuery. This behavior is $(this.toArray()).</summary>
26
+ return $(this.toArray());
27
+ };
28
+ })(this);
@@ -0,0 +1,3 @@
1
+ //= require linq.lib
2
+ //= require linq.rx
3
+ //= require link.jquery
@@ -0,0 +1,2997 @@
1
+ /*--------------------------------------------------------------------------
2
+ * linq.js - LINQ for JavaScript
3
+ * ver 3.0.3-Beta4 (Oct. 9th, 2012)
4
+ *
5
+ * created and maintained by neuecc <ils@neue.cc>
6
+ * licensed under MIT License
7
+ * http://linqjs.codeplex.com/
8
+ *------------------------------------------------------------------------*/
9
+
10
+ (function (root, undefined) {
11
+ // ReadOnly Function
12
+ var Functions = {
13
+ Identity: function (x) { return x; },
14
+ True: function () { return true; },
15
+ Blank: function () { }
16
+ };
17
+
18
+ // const Type
19
+ var Types = {
20
+ Boolean: typeof true,
21
+ Number: typeof 0,
22
+ String: typeof "",
23
+ Object: typeof {},
24
+ Undefined: typeof undefined,
25
+ Function: typeof function () { }
26
+ };
27
+
28
+ // private utility methods
29
+ var Utils = {
30
+ // Create anonymous function from lambda expression string
31
+ createLambda: function (expression) {
32
+ if (expression == null) return Functions.Identity;
33
+ if (typeof expression == Types.String) {
34
+ if (expression == "") {
35
+ return Functions.Identity;
36
+ }
37
+ else if (expression.indexOf("=>") == -1) {
38
+ var regexp = new RegExp("[$]+", "g");
39
+
40
+ var maxLength = 0;
41
+ var match;
42
+ while (match = regexp.exec(expression)) {
43
+ var paramNumber = match[0].length;
44
+ if (paramNumber > maxLength) {
45
+ maxLength = paramNumber;
46
+ }
47
+ }
48
+
49
+ var argArray = [];
50
+ for (var i = 1; i <= maxLength; i++) {
51
+ var dollar = "";
52
+ for (var j = 0; j < i; j++) {
53
+ dollar += "$";
54
+ }
55
+ argArray.push(dollar);
56
+ }
57
+
58
+ var args = Array.prototype.join.call(argArray, ",");
59
+
60
+ return new Function(args, "return " + expression);
61
+ }
62
+ else {
63
+ var expr = expression.match(/^[(\s]*([^()]*?)[)\s]*=>(.*)/);
64
+ return new Function(expr[1], "return " + expr[2]);
65
+ }
66
+ }
67
+ return expression;
68
+ },
69
+
70
+ isIEnumerable: function (obj) {
71
+ if (typeof Enumerator !== Types.Undefined) {
72
+ try {
73
+ new Enumerator(obj); // check JScript(IE)'s Enumerator
74
+ return true;
75
+ }
76
+ catch (e) { }
77
+ }
78
+
79
+ return false;
80
+ },
81
+
82
+ // IE8's defineProperty is defined but cannot use, therefore check defineProperties
83
+ defineProperty: (Object.defineProperties != null)
84
+ ? function (target, methodName, value) {
85
+ Object.defineProperty(target, methodName, {
86
+ enumerable: false,
87
+ configurable: true,
88
+ writable: true,
89
+ value: value
90
+ })
91
+ }
92
+ : function (target, methodName, value) {
93
+ target[methodName] = value;
94
+ },
95
+
96
+ compare: function (a, b) {
97
+ return (a === b) ? 0
98
+ : (a > b) ? 1
99
+ : -1;
100
+ },
101
+
102
+ dispose: function (obj) {
103
+ if (obj != null) obj.dispose();
104
+ }
105
+ };
106
+
107
+ // IEnumerator State
108
+ var State = { Before: 0, Running: 1, After: 2 };
109
+
110
+ // "Enumerator" is conflict JScript's "Enumerator"
111
+ var IEnumerator = function (initialize, tryGetNext, dispose) {
112
+ var yielder = new Yielder();
113
+ var state = State.Before;
114
+
115
+ this.current = yielder.current;
116
+
117
+ this.moveNext = function () {
118
+ try {
119
+ switch (state) {
120
+ case State.Before:
121
+ state = State.Running;
122
+ initialize();
123
+ // fall through
124
+ case State.Running:
125
+ if (tryGetNext.apply(yielder)) {
126
+ return true;
127
+ }
128
+ else {
129
+ this.dispose();
130
+ return false;
131
+ }
132
+ case State.After:
133
+ return false;
134
+ }
135
+ }
136
+ catch (e) {
137
+ this.dispose();
138
+ throw e;
139
+ }
140
+ };
141
+
142
+ this.dispose = function () {
143
+ if (state != State.Running) return;
144
+
145
+ try {
146
+ dispose();
147
+ }
148
+ finally {
149
+ state = State.After;
150
+ }
151
+ };
152
+ };
153
+
154
+ // for tryGetNext
155
+ var Yielder = function () {
156
+ var current = null;
157
+ this.current = function () { return current; };
158
+ this.yieldReturn = function (value) {
159
+ current = value;
160
+ return true;
161
+ };
162
+ this.yieldBreak = function () {
163
+ return false;
164
+ };
165
+ };
166
+
167
+ // Enumerable constuctor
168
+ var Enumerable = function (getEnumerator) {
169
+ this.getEnumerator = getEnumerator;
170
+ };
171
+
172
+ // Utility
173
+
174
+ Enumerable.Utils = {}; // container
175
+
176
+ Enumerable.Utils.createLambda = function (expression) {
177
+ return Utils.createLambda(expression);
178
+ };
179
+
180
+ Enumerable.Utils.createEnumerable = function (getEnumerator) {
181
+ return new Enumerable(getEnumerator);
182
+ };
183
+
184
+ Enumerable.Utils.createEnumerator = function (initialize, tryGetNext, dispose) {
185
+ return new IEnumerator(initialize, tryGetNext, dispose);
186
+ };
187
+
188
+ Enumerable.Utils.extendTo = function (type) {
189
+ var typeProto = type.prototype;
190
+ var enumerableProto;
191
+
192
+ if (type === Array) {
193
+ enumerableProto = ArrayEnumerable.prototype;
194
+ Utils.defineProperty(typeProto, "getSource", function () {
195
+ return this;
196
+ });
197
+ }
198
+ else {
199
+ enumerableProto = Enumerable.prototype;
200
+ Utils.defineProperty(typeProto, "getEnumerator", function () {
201
+ return Enumerable.from(this).getEnumerator();
202
+ });
203
+ }
204
+
205
+ for (var methodName in enumerableProto) {
206
+ var func = enumerableProto[methodName];
207
+
208
+ // already extended
209
+ if (typeProto[methodName] == func) continue;
210
+
211
+ // already defined(example Array#reverse/join/forEach...)
212
+ if (typeProto[methodName] != null) {
213
+ methodName = methodName + "ByLinq";
214
+ if (typeProto[methodName] == func) continue; // recheck
215
+ }
216
+
217
+ if (func instanceof Function) {
218
+ Utils.defineProperty(typeProto, methodName, func);
219
+ }
220
+ }
221
+ };
222
+
223
+ // Generator
224
+
225
+ Enumerable.choice = function () // variable argument
226
+ {
227
+ var args = arguments;
228
+
229
+ return new Enumerable(function () {
230
+ return new IEnumerator(
231
+ function () {
232
+ args = (args[0] instanceof Array) ? args[0]
233
+ : (args[0].getEnumerator != null) ? args[0].toArray()
234
+ : args;
235
+ },
236
+ function () {
237
+ return this.yieldReturn(args[Math.floor(Math.random() * args.length)]);
238
+ },
239
+ Functions.Blank);
240
+ });
241
+ };
242
+
243
+ Enumerable.cycle = function () // variable argument
244
+ {
245
+ var args = arguments;
246
+
247
+ return new Enumerable(function () {
248
+ var index = 0;
249
+ return new IEnumerator(
250
+ function () {
251
+ args = (args[0] instanceof Array) ? args[0]
252
+ : (args[0].getEnumerator != null) ? args[0].toArray()
253
+ : args;
254
+ },
255
+ function () {
256
+ if (index >= args.length) index = 0;
257
+ return this.yieldReturn(args[index++]);
258
+ },
259
+ Functions.Blank);
260
+ });
261
+ };
262
+
263
+ Enumerable.empty = function () {
264
+ return new Enumerable(function () {
265
+ return new IEnumerator(
266
+ Functions.Blank,
267
+ function () { return false; },
268
+ Functions.Blank);
269
+ });
270
+ };
271
+
272
+ Enumerable.from = function (obj) {
273
+ if (obj == null) {
274
+ return Enumerable.empty();
275
+ }
276
+ if (obj instanceof Enumerable) {
277
+ return obj;
278
+ }
279
+ if (typeof obj == Types.Number || typeof obj == Types.Boolean) {
280
+ return Enumerable.repeat(obj, 1);
281
+ }
282
+ if (typeof obj == Types.String) {
283
+ return new Enumerable(function () {
284
+ var index = 0;
285
+ return new IEnumerator(
286
+ Functions.Blank,
287
+ function () {
288
+ return (index < obj.length) ? this.yieldReturn(obj.charAt(index++)) : false;
289
+ },
290
+ Functions.Blank);
291
+ });
292
+ }
293
+ if (typeof obj != Types.Function) {
294
+ // array or array like object
295
+ if (typeof obj.length == Types.Number) {
296
+ return new ArrayEnumerable(obj);
297
+ }
298
+
299
+ // JScript's IEnumerable
300
+ if (!(obj instanceof Object) && Utils.isIEnumerable(obj)) {
301
+ return new Enumerable(function () {
302
+ var isFirst = true;
303
+ var enumerator;
304
+ return new IEnumerator(
305
+ function () { enumerator = new Enumerator(obj); },
306
+ function () {
307
+ if (isFirst) isFirst = false;
308
+ else enumerator.moveNext();
309
+
310
+ return (enumerator.atEnd()) ? false : this.yieldReturn(enumerator.item());
311
+ },
312
+ Functions.Blank);
313
+ });
314
+ }
315
+
316
+ // WinMD IIterable<T>
317
+ if (typeof Windows === Types.Object && typeof obj.first === Types.Function) {
318
+ return new Enumerable(function () {
319
+ var isFirst = true;
320
+ var enumerator;
321
+ return new IEnumerator(
322
+ function () { enumerator = obj.first(); },
323
+ function () {
324
+ if (isFirst) isFirst = false;
325
+ else enumerator.moveNext();
326
+
327
+ return (enumerator.hasCurrent) ? this.yieldReturn(enumerator.current) : this.yieldBreak();
328
+ },
329
+ Functions.Blank);
330
+ });
331
+ }
332
+ }
333
+
334
+ // case function/object : Create keyValuePair[]
335
+ return new Enumerable(function () {
336
+ var array = [];
337
+ var index = 0;
338
+
339
+ return new IEnumerator(
340
+ function () {
341
+ for (var key in obj) {
342
+ var value = obj[key];
343
+ if (!(value instanceof Function) && Object.prototype.hasOwnProperty.call(obj, key)) {
344
+ array.push({ key: key, value: value });
345
+ }
346
+ }
347
+ },
348
+ function () {
349
+ return (index < array.length)
350
+ ? this.yieldReturn(array[index++])
351
+ : false;
352
+ },
353
+ Functions.Blank);
354
+ });
355
+ },
356
+
357
+ Enumerable.make = function (element) {
358
+ return Enumerable.repeat(element, 1);
359
+ };
360
+
361
+ // Overload:function(input, pattern)
362
+ // Overload:function(input, pattern, flags)
363
+ Enumerable.matches = function (input, pattern, flags) {
364
+ if (flags == null) flags = "";
365
+ if (pattern instanceof RegExp) {
366
+ flags += (pattern.ignoreCase) ? "i" : "";
367
+ flags += (pattern.multiline) ? "m" : "";
368
+ pattern = pattern.source;
369
+ }
370
+ if (flags.indexOf("g") === -1) flags += "g";
371
+
372
+ return new Enumerable(function () {
373
+ var regex;
374
+ return new IEnumerator(
375
+ function () { regex = new RegExp(pattern, flags); },
376
+ function () {
377
+ var match = regex.exec(input);
378
+ return (match) ? this.yieldReturn(match) : false;
379
+ },
380
+ Functions.Blank);
381
+ });
382
+ };
383
+
384
+ // Overload:function(start, count)
385
+ // Overload:function(start, count, step)
386
+ Enumerable.range = function (start, count, step) {
387
+ if (step == null) step = 1;
388
+
389
+ return new Enumerable(function () {
390
+ var value;
391
+ var index = 0;
392
+
393
+ return new IEnumerator(
394
+ function () { value = start - step; },
395
+ function () {
396
+ return (index++ < count)
397
+ ? this.yieldReturn(value += step)
398
+ : this.yieldBreak();
399
+ },
400
+ Functions.Blank);
401
+ });
402
+ };
403
+
404
+ // Overload:function(start, count)
405
+ // Overload:function(start, count, step)
406
+ Enumerable.rangeDown = function (start, count, step) {
407
+ if (step == null) step = 1;
408
+
409
+ return new Enumerable(function () {
410
+ var value;
411
+ var index = 0;
412
+
413
+ return new IEnumerator(
414
+ function () { value = start + step; },
415
+ function () {
416
+ return (index++ < count)
417
+ ? this.yieldReturn(value -= step)
418
+ : this.yieldBreak();
419
+ },
420
+ Functions.Blank);
421
+ });
422
+ };
423
+
424
+ // Overload:function(start, to)
425
+ // Overload:function(start, to, step)
426
+ Enumerable.rangeTo = function (start, to, step) {
427
+ if (step == null) step = 1;
428
+
429
+ if (start < to) {
430
+ return new Enumerable(function () {
431
+ var value;
432
+
433
+ return new IEnumerator(
434
+ function () { value = start - step; },
435
+ function () {
436
+ var next = value += step;
437
+ return (next <= to)
438
+ ? this.yieldReturn(next)
439
+ : this.yieldBreak();
440
+ },
441
+ Functions.Blank);
442
+ });
443
+ }
444
+ else {
445
+ return new Enumerable(function () {
446
+ var value;
447
+
448
+ return new IEnumerator(
449
+ function () { value = start + step; },
450
+ function () {
451
+ var next = value -= step;
452
+ return (next >= to)
453
+ ? this.yieldReturn(next)
454
+ : this.yieldBreak();
455
+ },
456
+ Functions.Blank);
457
+ });
458
+ }
459
+ };
460
+
461
+ // Overload:function(element)
462
+ // Overload:function(element, count)
463
+ Enumerable.repeat = function (element, count) {
464
+ if (count != null) return Enumerable.repeat(element).take(count);
465
+
466
+ return new Enumerable(function () {
467
+ return new IEnumerator(
468
+ Functions.Blank,
469
+ function () { return this.yieldReturn(element); },
470
+ Functions.Blank);
471
+ });
472
+ };
473
+
474
+ Enumerable.repeatWithFinalize = function (initializer, finalizer) {
475
+ initializer = Utils.createLambda(initializer);
476
+ finalizer = Utils.createLambda(finalizer);
477
+
478
+ return new Enumerable(function () {
479
+ var element;
480
+ return new IEnumerator(
481
+ function () { element = initializer(); },
482
+ function () { return this.yieldReturn(element); },
483
+ function () {
484
+ if (element != null) {
485
+ finalizer(element);
486
+ element = null;
487
+ }
488
+ });
489
+ });
490
+ };
491
+
492
+ // Overload:function(func)
493
+ // Overload:function(func, count)
494
+ Enumerable.generate = function (func, count) {
495
+ if (count != null) return Enumerable.generate(func).take(count);
496
+ func = Utils.createLambda(func);
497
+
498
+ return new Enumerable(function () {
499
+ return new IEnumerator(
500
+ Functions.Blank,
501
+ function () { return this.yieldReturn(func()); },
502
+ Functions.Blank);
503
+ });
504
+ };
505
+
506
+ // Overload:function()
507
+ // Overload:function(start)
508
+ // Overload:function(start, step)
509
+ Enumerable.toInfinity = function (start, step) {
510
+ if (start == null) start = 0;
511
+ if (step == null) step = 1;
512
+
513
+ return new Enumerable(function () {
514
+ var value;
515
+ return new IEnumerator(
516
+ function () { value = start - step; },
517
+ function () { return this.yieldReturn(value += step); },
518
+ Functions.Blank);
519
+ });
520
+ };
521
+
522
+ // Overload:function()
523
+ // Overload:function(start)
524
+ // Overload:function(start, step)
525
+ Enumerable.toNegativeInfinity = function (start, step) {
526
+ if (start == null) start = 0;
527
+ if (step == null) step = 1;
528
+
529
+ return new Enumerable(function () {
530
+ var value;
531
+ return new IEnumerator(
532
+ function () { value = start + step; },
533
+ function () { return this.yieldReturn(value -= step); },
534
+ Functions.Blank);
535
+ });
536
+ };
537
+
538
+ Enumerable.unfold = function (seed, func) {
539
+ func = Utils.createLambda(func);
540
+
541
+ return new Enumerable(function () {
542
+ var isFirst = true;
543
+ var value;
544
+ return new IEnumerator(
545
+ Functions.Blank,
546
+ function () {
547
+ if (isFirst) {
548
+ isFirst = false;
549
+ value = seed;
550
+ return this.yieldReturn(value);
551
+ }
552
+ value = func(value);
553
+ return this.yieldReturn(value);
554
+ },
555
+ Functions.Blank);
556
+ });
557
+ };
558
+
559
+ Enumerable.defer = function (enumerableFactory) {
560
+
561
+ return new Enumerable(function () {
562
+ var enumerator;
563
+
564
+ return new IEnumerator(
565
+ function () { enumerator = Enumerable.from(enumerableFactory()).getEnumerator(); },
566
+ function () {
567
+ return (enumerator.moveNext())
568
+ ? this.yieldReturn(enumerator.current())
569
+ : this.yieldBreak();
570
+ },
571
+ function () {
572
+ Utils.dispose(enumerator);
573
+ });
574
+ });
575
+ };
576
+
577
+ // Extension Methods
578
+
579
+ /* Projection and Filtering Methods */
580
+
581
+ // Overload:function(func)
582
+ // Overload:function(func, resultSelector<element>)
583
+ // Overload:function(func, resultSelector<element, nestLevel>)
584
+ Enumerable.prototype.traverseBreadthFirst = function (func, resultSelector) {
585
+ var source = this;
586
+ func = Utils.createLambda(func);
587
+ resultSelector = Utils.createLambda(resultSelector);
588
+
589
+ return new Enumerable(function () {
590
+ var enumerator;
591
+ var nestLevel = 0;
592
+ var buffer = [];
593
+
594
+ return new IEnumerator(
595
+ function () { enumerator = source.getEnumerator(); },
596
+ function () {
597
+ while (true) {
598
+ if (enumerator.moveNext()) {
599
+ buffer.push(enumerator.current());
600
+ return this.yieldReturn(resultSelector(enumerator.current(), nestLevel));
601
+ }
602
+
603
+ var next = Enumerable.from(buffer).selectMany(function (x) { return func(x); });
604
+ if (!next.any()) {
605
+ return false;
606
+ }
607
+ else {
608
+ nestLevel++;
609
+ buffer = [];
610
+ Utils.dispose(enumerator);
611
+ enumerator = next.getEnumerator();
612
+ }
613
+ }
614
+ },
615
+ function () { Utils.dispose(enumerator); });
616
+ });
617
+ };
618
+
619
+ // Overload:function(func)
620
+ // Overload:function(func, resultSelector<element>)
621
+ // Overload:function(func, resultSelector<element, nestLevel>)
622
+ Enumerable.prototype.traverseDepthFirst = function (func, resultSelector) {
623
+ var source = this;
624
+ func = Utils.createLambda(func);
625
+ resultSelector = Utils.createLambda(resultSelector);
626
+
627
+ return new Enumerable(function () {
628
+ var enumeratorStack = [];
629
+ var enumerator;
630
+
631
+ return new IEnumerator(
632
+ function () { enumerator = source.getEnumerator(); },
633
+ function () {
634
+ while (true) {
635
+ if (enumerator.moveNext()) {
636
+ var value = resultSelector(enumerator.current(), enumeratorStack.length);
637
+ enumeratorStack.push(enumerator);
638
+ enumerator = Enumerable.from(func(enumerator.current())).getEnumerator();
639
+ return this.yieldReturn(value);
640
+ }
641
+
642
+ if (enumeratorStack.length <= 0) return false;
643
+ Utils.dispose(enumerator);
644
+ enumerator = enumeratorStack.pop();
645
+ }
646
+ },
647
+ function () {
648
+ try {
649
+ Utils.dispose(enumerator);
650
+ }
651
+ finally {
652
+ Enumerable.from(enumeratorStack).forEach(function (s) { s.dispose(); });
653
+ }
654
+ });
655
+ });
656
+ };
657
+
658
+ Enumerable.prototype.flatten = function () {
659
+ var source = this;
660
+
661
+ return new Enumerable(function () {
662
+ var enumerator;
663
+ var middleEnumerator = null;
664
+
665
+ return new IEnumerator(
666
+ function () { enumerator = source.getEnumerator(); },
667
+ function () {
668
+ while (true) {
669
+ if (middleEnumerator != null) {
670
+ if (middleEnumerator.moveNext()) {
671
+ return this.yieldReturn(middleEnumerator.current());
672
+ }
673
+ else {
674
+ middleEnumerator = null;
675
+ }
676
+ }
677
+
678
+ if (enumerator.moveNext()) {
679
+ if (enumerator.current() instanceof Array) {
680
+ Utils.dispose(middleEnumerator);
681
+ middleEnumerator = Enumerable.from(enumerator.current())
682
+ .selectMany(Functions.Identity)
683
+ .flatten()
684
+ .getEnumerator();
685
+ continue;
686
+ }
687
+ else {
688
+ return this.yieldReturn(enumerator.current());
689
+ }
690
+ }
691
+
692
+ return false;
693
+ }
694
+ },
695
+ function () {
696
+ try {
697
+ Utils.dispose(enumerator);
698
+ }
699
+ finally {
700
+ Utils.dispose(middleEnumerator);
701
+ }
702
+ });
703
+ });
704
+ };
705
+
706
+ Enumerable.prototype.pairwise = function (selector) {
707
+ var source = this;
708
+ selector = Utils.createLambda(selector);
709
+
710
+ return new Enumerable(function () {
711
+ var enumerator;
712
+
713
+ return new IEnumerator(
714
+ function () {
715
+ enumerator = source.getEnumerator();
716
+ enumerator.moveNext();
717
+ },
718
+ function () {
719
+ var prev = enumerator.current();
720
+ return (enumerator.moveNext())
721
+ ? this.yieldReturn(selector(prev, enumerator.current()))
722
+ : false;
723
+ },
724
+ function () { Utils.dispose(enumerator); });
725
+ });
726
+ };
727
+
728
+ // Overload:function(func)
729
+ // Overload:function(seed,func<value,element>)
730
+ Enumerable.prototype.scan = function (seed, func) {
731
+ var isUseSeed;
732
+ if (func == null) {
733
+ func = Utils.createLambda(seed); // arguments[0]
734
+ isUseSeed = false;
735
+ } else {
736
+ func = Utils.createLambda(func);
737
+ isUseSeed = true;
738
+ }
739
+ var source = this;
740
+
741
+ return new Enumerable(function () {
742
+ var enumerator;
743
+ var value;
744
+ var isFirst = true;
745
+
746
+ return new IEnumerator(
747
+ function () { enumerator = source.getEnumerator(); },
748
+ function () {
749
+ if (isFirst) {
750
+ isFirst = false;
751
+ if (!isUseSeed) {
752
+ if (enumerator.moveNext()) {
753
+ return this.yieldReturn(value = enumerator.current());
754
+ }
755
+ }
756
+ else {
757
+ return this.yieldReturn(value = seed);
758
+ }
759
+ }
760
+
761
+ return (enumerator.moveNext())
762
+ ? this.yieldReturn(value = func(value, enumerator.current()))
763
+ : false;
764
+ },
765
+ function () { Utils.dispose(enumerator); });
766
+ });
767
+ };
768
+
769
+ // Overload:function(selector<element>)
770
+ // Overload:function(selector<element,index>)
771
+ Enumerable.prototype.select = function (selector) {
772
+ selector = Utils.createLambda(selector);
773
+
774
+ if (selector.length <= 1) {
775
+ return new WhereSelectEnumerable(this, null, selector);
776
+ }
777
+ else {
778
+ var source = this;
779
+
780
+ return new Enumerable(function () {
781
+ var enumerator;
782
+ var index = 0;
783
+
784
+ return new IEnumerator(
785
+ function () { enumerator = source.getEnumerator(); },
786
+ function () {
787
+ return (enumerator.moveNext())
788
+ ? this.yieldReturn(selector(enumerator.current(), index++))
789
+ : false;
790
+ },
791
+ function () { Utils.dispose(enumerator); });
792
+ });
793
+ }
794
+ };
795
+
796
+ // Overload:function(collectionSelector<element>)
797
+ // Overload:function(collectionSelector<element,index>)
798
+ // Overload:function(collectionSelector<element>,resultSelector)
799
+ // Overload:function(collectionSelector<element,index>,resultSelector)
800
+ Enumerable.prototype.selectMany = function (collectionSelector, resultSelector) {
801
+ var source = this;
802
+ collectionSelector = Utils.createLambda(collectionSelector);
803
+ if (resultSelector == null) resultSelector = function (a, b) { return b; };
804
+ resultSelector = Utils.createLambda(resultSelector);
805
+
806
+ return new Enumerable(function () {
807
+ var enumerator;
808
+ var middleEnumerator = undefined;
809
+ var index = 0;
810
+
811
+ return new IEnumerator(
812
+ function () { enumerator = source.getEnumerator(); },
813
+ function () {
814
+ if (middleEnumerator === undefined) {
815
+ if (!enumerator.moveNext()) return false;
816
+ }
817
+ do {
818
+ if (middleEnumerator == null) {
819
+ var middleSeq = collectionSelector(enumerator.current(), index++);
820
+ middleEnumerator = Enumerable.from(middleSeq).getEnumerator();
821
+ }
822
+ if (middleEnumerator.moveNext()) {
823
+ return this.yieldReturn(resultSelector(enumerator.current(), middleEnumerator.current()));
824
+ }
825
+ Utils.dispose(middleEnumerator);
826
+ middleEnumerator = null;
827
+ } while (enumerator.moveNext());
828
+ return false;
829
+ },
830
+ function () {
831
+ try {
832
+ Utils.dispose(enumerator);
833
+ }
834
+ finally {
835
+ Utils.dispose(middleEnumerator);
836
+ }
837
+ });
838
+ });
839
+ };
840
+
841
+ // Overload:function(predicate<element>)
842
+ // Overload:function(predicate<element,index>)
843
+ Enumerable.prototype.where = function (predicate) {
844
+ predicate = Utils.createLambda(predicate);
845
+
846
+ if (predicate.length <= 1) {
847
+ return new WhereEnumerable(this, predicate);
848
+ }
849
+ else {
850
+ var source = this;
851
+
852
+ return new Enumerable(function () {
853
+ var enumerator;
854
+ var index = 0;
855
+
856
+ return new IEnumerator(
857
+ function () { enumerator = source.getEnumerator(); },
858
+ function () {
859
+ while (enumerator.moveNext()) {
860
+ if (predicate(enumerator.current(), index++)) {
861
+ return this.yieldReturn(enumerator.current());
862
+ }
863
+ }
864
+ return false;
865
+ },
866
+ function () { Utils.dispose(enumerator); });
867
+ });
868
+ }
869
+ };
870
+
871
+
872
+ // Overload:function(selector<element>)
873
+ // Overload:function(selector<element,index>)
874
+ Enumerable.prototype.choose = function (selector) {
875
+ selector = Utils.createLambda(selector);
876
+ var source = this;
877
+
878
+ return new Enumerable(function () {
879
+ var enumerator;
880
+ var index = 0;
881
+
882
+ return new IEnumerator(
883
+ function () { enumerator = source.getEnumerator(); },
884
+ function () {
885
+ while (enumerator.moveNext()) {
886
+ var result = selector(enumerator.current(), index++);
887
+ if (result != null) {
888
+ return this.yieldReturn(result);
889
+ }
890
+ }
891
+ return this.yieldBreak();
892
+ },
893
+ function () { Utils.dispose(enumerator); });
894
+ });
895
+ };
896
+
897
+ Enumerable.prototype.ofType = function (type) {
898
+ var typeName;
899
+ switch (type) {
900
+ case Number:
901
+ typeName = Types.Number;
902
+ break;
903
+ case String:
904
+ typeName = Types.String;
905
+ break;
906
+ case Boolean:
907
+ typeName = Types.Boolean;
908
+ break;
909
+ case Function:
910
+ typeName = Types.Function;
911
+ break;
912
+ default:
913
+ typeName = null;
914
+ break;
915
+ }
916
+ return (typeName === null)
917
+ ? this.where(function (x) { return x instanceof type; })
918
+ : this.where(function (x) { return typeof x === typeName; });
919
+ };
920
+
921
+ // mutiple arguments, last one is selector, others are enumerable
922
+ Enumerable.prototype.zip = function () {
923
+ var args = arguments;
924
+ var selector = Utils.createLambda(arguments[arguments.length - 1]);
925
+
926
+ var source = this;
927
+ // optimized case:argument is 2
928
+ if (arguments.length == 2) {
929
+ var second = arguments[0];
930
+
931
+ return new Enumerable(function () {
932
+ var firstEnumerator;
933
+ var secondEnumerator;
934
+ var index = 0;
935
+
936
+ return new IEnumerator(
937
+ function () {
938
+ firstEnumerator = source.getEnumerator();
939
+ secondEnumerator = Enumerable.from(second).getEnumerator();
940
+ },
941
+ function () {
942
+ if (firstEnumerator.moveNext() && secondEnumerator.moveNext()) {
943
+ return this.yieldReturn(selector(firstEnumerator.current(), secondEnumerator.current(), index++));
944
+ }
945
+ return false;
946
+ },
947
+ function () {
948
+ try {
949
+ Utils.dispose(firstEnumerator);
950
+ } finally {
951
+ Utils.dispose(secondEnumerator);
952
+ }
953
+ });
954
+ });
955
+ }
956
+ else {
957
+ return new Enumerable(function () {
958
+ var enumerators;
959
+ var index = 0;
960
+
961
+ return new IEnumerator(
962
+ function () {
963
+ var array = Enumerable.make(source)
964
+ .concat(Enumerable.from(args).takeExceptLast().select(Enumerable.from))
965
+ .select(function (x) { return x.getEnumerator() })
966
+ .toArray();
967
+ enumerators = Enumerable.from(array);
968
+ },
969
+ function () {
970
+ if (enumerators.all(function (x) { return x.moveNext() })) {
971
+ var array = enumerators
972
+ .select(function (x) { return x.current() })
973
+ .toArray();
974
+ array.push(index++);
975
+ return this.yieldReturn(selector.apply(null, array));
976
+ }
977
+ else {
978
+ return this.yieldBreak();
979
+ }
980
+ },
981
+ function () {
982
+ Enumerable.from(enumerators).forEach(Utils.dispose);
983
+ });
984
+ });
985
+ }
986
+ };
987
+
988
+ // mutiple arguments
989
+ Enumerable.prototype.merge = function () {
990
+ var args = arguments;
991
+ var source = this;
992
+
993
+ return new Enumerable(function () {
994
+ var enumerators;
995
+ var index = -1;
996
+
997
+ return new IEnumerator(
998
+ function () {
999
+ enumerators = Enumerable.make(source)
1000
+ .concat(Enumerable.from(args).select(Enumerable.from))
1001
+ .select(function (x) { return x.getEnumerator() })
1002
+ .toArray();
1003
+ },
1004
+ function () {
1005
+ while (enumerators.length > 0) {
1006
+ index = (index >= enumerators.length - 1) ? 0 : index + 1;
1007
+ var enumerator = enumerators[index];
1008
+
1009
+ if (enumerator.moveNext()) {
1010
+ return this.yieldReturn(enumerator.current());
1011
+ }
1012
+ else {
1013
+ enumerator.dispose();
1014
+ enumerators.splice(index--, 1);
1015
+ }
1016
+ }
1017
+ return this.yieldBreak();
1018
+ },
1019
+ function () {
1020
+ Enumerable.from(enumerators).forEach(Utils.dispose);
1021
+ });
1022
+ });
1023
+ };
1024
+
1025
+ /* Join Methods */
1026
+
1027
+ // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector)
1028
+ // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector)
1029
+ Enumerable.prototype.join = function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) {
1030
+ outerKeySelector = Utils.createLambda(outerKeySelector);
1031
+ innerKeySelector = Utils.createLambda(innerKeySelector);
1032
+ resultSelector = Utils.createLambda(resultSelector);
1033
+ compareSelector = Utils.createLambda(compareSelector);
1034
+ var source = this;
1035
+
1036
+ return new Enumerable(function () {
1037
+ var outerEnumerator;
1038
+ var lookup;
1039
+ var innerElements = null;
1040
+ var innerCount = 0;
1041
+
1042
+ return new IEnumerator(
1043
+ function () {
1044
+ outerEnumerator = source.getEnumerator();
1045
+ lookup = Enumerable.from(inner).toLookup(innerKeySelector, Functions.Identity, compareSelector);
1046
+ },
1047
+ function () {
1048
+ while (true) {
1049
+ if (innerElements != null) {
1050
+ var innerElement = innerElements[innerCount++];
1051
+ if (innerElement !== undefined) {
1052
+ return this.yieldReturn(resultSelector(outerEnumerator.current(), innerElement));
1053
+ }
1054
+
1055
+ innerElement = null;
1056
+ innerCount = 0;
1057
+ }
1058
+
1059
+ if (outerEnumerator.moveNext()) {
1060
+ var key = outerKeySelector(outerEnumerator.current());
1061
+ innerElements = lookup.get(key).toArray();
1062
+ } else {
1063
+ return false;
1064
+ }
1065
+ }
1066
+ },
1067
+ function () { Utils.dispose(outerEnumerator); });
1068
+ });
1069
+ };
1070
+
1071
+ // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector)
1072
+ // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector)
1073
+ Enumerable.prototype.groupJoin = function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) {
1074
+ outerKeySelector = Utils.createLambda(outerKeySelector);
1075
+ innerKeySelector = Utils.createLambda(innerKeySelector);
1076
+ resultSelector = Utils.createLambda(resultSelector);
1077
+ compareSelector = Utils.createLambda(compareSelector);
1078
+ var source = this;
1079
+
1080
+ return new Enumerable(function () {
1081
+ var enumerator = source.getEnumerator();
1082
+ var lookup = null;
1083
+
1084
+ return new IEnumerator(
1085
+ function () {
1086
+ enumerator = source.getEnumerator();
1087
+ lookup = Enumerable.from(inner).toLookup(innerKeySelector, Functions.Identity, compareSelector);
1088
+ },
1089
+ function () {
1090
+ if (enumerator.moveNext()) {
1091
+ var innerElement = lookup.get(outerKeySelector(enumerator.current()));
1092
+ return this.yieldReturn(resultSelector(enumerator.current(), innerElement));
1093
+ }
1094
+ return false;
1095
+ },
1096
+ function () { Utils.dispose(enumerator); });
1097
+ });
1098
+ };
1099
+
1100
+ /* Set Methods */
1101
+
1102
+ Enumerable.prototype.all = function (predicate) {
1103
+ predicate = Utils.createLambda(predicate);
1104
+
1105
+ var result = true;
1106
+ this.forEach(function (x) {
1107
+ if (!predicate(x)) {
1108
+ result = false;
1109
+ return false; // break
1110
+ }
1111
+ });
1112
+ return result;
1113
+ };
1114
+
1115
+ // Overload:function()
1116
+ // Overload:function(predicate)
1117
+ Enumerable.prototype.any = function (predicate) {
1118
+ predicate = Utils.createLambda(predicate);
1119
+
1120
+ var enumerator = this.getEnumerator();
1121
+ try {
1122
+ if (arguments.length == 0) return enumerator.moveNext(); // case:function()
1123
+
1124
+ while (enumerator.moveNext()) // case:function(predicate)
1125
+ {
1126
+ if (predicate(enumerator.current())) return true;
1127
+ }
1128
+ return false;
1129
+ }
1130
+ finally {
1131
+ Utils.dispose(enumerator);
1132
+ }
1133
+ };
1134
+
1135
+ Enumerable.prototype.isEmpty = function () {
1136
+ return !this.any();
1137
+ };
1138
+
1139
+ // multiple arguments
1140
+ Enumerable.prototype.concat = function () {
1141
+ var source = this;
1142
+
1143
+ if (arguments.length == 1) {
1144
+ var second = arguments[0];
1145
+
1146
+ return new Enumerable(function () {
1147
+ var firstEnumerator;
1148
+ var secondEnumerator;
1149
+
1150
+ return new IEnumerator(
1151
+ function () { firstEnumerator = source.getEnumerator(); },
1152
+ function () {
1153
+ if (secondEnumerator == null) {
1154
+ if (firstEnumerator.moveNext()) return this.yieldReturn(firstEnumerator.current());
1155
+ secondEnumerator = Enumerable.from(second).getEnumerator();
1156
+ }
1157
+ if (secondEnumerator.moveNext()) return this.yieldReturn(secondEnumerator.current());
1158
+ return false;
1159
+ },
1160
+ function () {
1161
+ try {
1162
+ Utils.dispose(firstEnumerator);
1163
+ }
1164
+ finally {
1165
+ Utils.dispose(secondEnumerator);
1166
+ }
1167
+ });
1168
+ });
1169
+ }
1170
+ else {
1171
+ var args = arguments;
1172
+
1173
+ return new Enumerable(function () {
1174
+ var enumerators;
1175
+
1176
+ return new IEnumerator(
1177
+ function () {
1178
+ enumerators = Enumerable.make(source)
1179
+ .concat(Enumerable.from(args).select(Enumerable.from))
1180
+ .select(function (x) { return x.getEnumerator() })
1181
+ .toArray();
1182
+ },
1183
+ function () {
1184
+ while (enumerators.length > 0) {
1185
+ var enumerator = enumerators[0];
1186
+
1187
+ if (enumerator.moveNext()) {
1188
+ return this.yieldReturn(enumerator.current());
1189
+ }
1190
+ else {
1191
+ enumerator.dispose();
1192
+ enumerators.splice(0, 1);
1193
+ }
1194
+ }
1195
+ return this.yieldBreak();
1196
+ },
1197
+ function () {
1198
+ Enumerable.from(enumerators).forEach(Utils.dispose);
1199
+ });
1200
+ });
1201
+ }
1202
+ };
1203
+
1204
+ Enumerable.prototype.insert = function (index, second) {
1205
+ var source = this;
1206
+
1207
+ return new Enumerable(function () {
1208
+ var firstEnumerator;
1209
+ var secondEnumerator;
1210
+ var count = 0;
1211
+ var isEnumerated = false;
1212
+
1213
+ return new IEnumerator(
1214
+ function () {
1215
+ firstEnumerator = source.getEnumerator();
1216
+ secondEnumerator = Enumerable.from(second).getEnumerator();
1217
+ },
1218
+ function () {
1219
+ if (count == index && secondEnumerator.moveNext()) {
1220
+ isEnumerated = true;
1221
+ return this.yieldReturn(secondEnumerator.current());
1222
+ }
1223
+ if (firstEnumerator.moveNext()) {
1224
+ count++;
1225
+ return this.yieldReturn(firstEnumerator.current());
1226
+ }
1227
+ if (!isEnumerated && secondEnumerator.moveNext()) {
1228
+ return this.yieldReturn(secondEnumerator.current());
1229
+ }
1230
+ return false;
1231
+ },
1232
+ function () {
1233
+ try {
1234
+ Utils.dispose(firstEnumerator);
1235
+ }
1236
+ finally {
1237
+ Utils.dispose(secondEnumerator);
1238
+ }
1239
+ });
1240
+ });
1241
+ };
1242
+
1243
+ Enumerable.prototype.alternate = function (alternateValueOrSequence) {
1244
+ var source = this;
1245
+
1246
+ return new Enumerable(function () {
1247
+ var buffer;
1248
+ var enumerator;
1249
+ var alternateSequence;
1250
+ var alternateEnumerator;
1251
+
1252
+ return new IEnumerator(
1253
+ function () {
1254
+ if (alternateValueOrSequence instanceof Array || alternateValueOrSequence.getEnumerator != null) {
1255
+ alternateSequence = Enumerable.from(Enumerable.from(alternateValueOrSequence).toArray()); // freeze
1256
+ }
1257
+ else {
1258
+ alternateSequence = Enumerable.make(alternateValueOrSequence);
1259
+ }
1260
+ enumerator = source.getEnumerator();
1261
+ if (enumerator.moveNext()) buffer = enumerator.current();
1262
+ },
1263
+ function () {
1264
+ while (true) {
1265
+ if (alternateEnumerator != null) {
1266
+ if (alternateEnumerator.moveNext()) {
1267
+ return this.yieldReturn(alternateEnumerator.current());
1268
+ }
1269
+ else {
1270
+ alternateEnumerator = null;
1271
+ }
1272
+ }
1273
+
1274
+ if (buffer == null && enumerator.moveNext()) {
1275
+ buffer = enumerator.current(); // hasNext
1276
+ alternateEnumerator = alternateSequence.getEnumerator();
1277
+ continue; // GOTO
1278
+ }
1279
+ else if (buffer != null) {
1280
+ var retVal = buffer;
1281
+ buffer = null;
1282
+ return this.yieldReturn(retVal);
1283
+ }
1284
+
1285
+ return this.yieldBreak();
1286
+ }
1287
+ },
1288
+ function () {
1289
+ try {
1290
+ Utils.dispose(enumerator);
1291
+ }
1292
+ finally {
1293
+ Utils.dispose(alternateEnumerator);
1294
+ }
1295
+ });
1296
+ });
1297
+ };
1298
+
1299
+ // Overload:function(value)
1300
+ // Overload:function(value, compareSelector)
1301
+ Enumerable.prototype.contains = function (value, compareSelector) {
1302
+ compareSelector = Utils.createLambda(compareSelector);
1303
+ var enumerator = this.getEnumerator();
1304
+ try {
1305
+ while (enumerator.moveNext()) {
1306
+ if (compareSelector(enumerator.current()) === value) return true;
1307
+ }
1308
+ return false;
1309
+ }
1310
+ finally {
1311
+ Utils.dispose(enumerator);
1312
+ }
1313
+ };
1314
+
1315
+ Enumerable.prototype.defaultIfEmpty = function (defaultValue) {
1316
+ var source = this;
1317
+ if (defaultValue === undefined) defaultValue = null;
1318
+
1319
+ return new Enumerable(function () {
1320
+ var enumerator;
1321
+ var isFirst = true;
1322
+
1323
+ return new IEnumerator(
1324
+ function () { enumerator = source.getEnumerator(); },
1325
+ function () {
1326
+ if (enumerator.moveNext()) {
1327
+ isFirst = false;
1328
+ return this.yieldReturn(enumerator.current());
1329
+ }
1330
+ else if (isFirst) {
1331
+ isFirst = false;
1332
+ return this.yieldReturn(defaultValue);
1333
+ }
1334
+ return false;
1335
+ },
1336
+ function () { Utils.dispose(enumerator); });
1337
+ });
1338
+ };
1339
+
1340
+ // Overload:function()
1341
+ // Overload:function(compareSelector)
1342
+ Enumerable.prototype.distinct = function (compareSelector) {
1343
+ return this.except(Enumerable.empty(), compareSelector);
1344
+ };
1345
+
1346
+ Enumerable.prototype.distinctUntilChanged = function (compareSelector) {
1347
+ compareSelector = Utils.createLambda(compareSelector);
1348
+ var source = this;
1349
+
1350
+ return new Enumerable(function () {
1351
+ var enumerator;
1352
+ var compareKey;
1353
+ var initial;
1354
+
1355
+ return new IEnumerator(
1356
+ function () {
1357
+ enumerator = source.getEnumerator();
1358
+ },
1359
+ function () {
1360
+ while (enumerator.moveNext()) {
1361
+ var key = compareSelector(enumerator.current());
1362
+
1363
+ if (initial) {
1364
+ initial = false;
1365
+ compareKey = key;
1366
+ return this.yieldReturn(enumerator.current());
1367
+ }
1368
+
1369
+ if (compareKey === key) {
1370
+ continue;
1371
+ }
1372
+
1373
+ compareKey = key;
1374
+ return this.yieldReturn(enumerator.current());
1375
+ }
1376
+ return this.yieldBreak();
1377
+ },
1378
+ function () { Utils.dispose(enumerator); });
1379
+ });
1380
+ };
1381
+
1382
+ // Overload:function(second)
1383
+ // Overload:function(second, compareSelector)
1384
+ Enumerable.prototype.except = function (second, compareSelector) {
1385
+ compareSelector = Utils.createLambda(compareSelector);
1386
+ var source = this;
1387
+
1388
+ return new Enumerable(function () {
1389
+ var enumerator;
1390
+ var keys;
1391
+
1392
+ return new IEnumerator(
1393
+ function () {
1394
+ enumerator = source.getEnumerator();
1395
+ keys = new Dictionary(compareSelector);
1396
+ Enumerable.from(second).forEach(function (key) { keys.add(key); });
1397
+ },
1398
+ function () {
1399
+ while (enumerator.moveNext()) {
1400
+ var current = enumerator.current();
1401
+ if (!keys.contains(current)) {
1402
+ keys.add(current);
1403
+ return this.yieldReturn(current);
1404
+ }
1405
+ }
1406
+ return false;
1407
+ },
1408
+ function () { Utils.dispose(enumerator); });
1409
+ });
1410
+ };
1411
+
1412
+ // Overload:function(second)
1413
+ // Overload:function(second, compareSelector)
1414
+ Enumerable.prototype.intersect = function (second, compareSelector) {
1415
+ compareSelector = Utils.createLambda(compareSelector);
1416
+ var source = this;
1417
+
1418
+ return new Enumerable(function () {
1419
+ var enumerator;
1420
+ var keys;
1421
+ var outs;
1422
+
1423
+ return new IEnumerator(
1424
+ function () {
1425
+ enumerator = source.getEnumerator();
1426
+
1427
+ keys = new Dictionary(compareSelector);
1428
+ Enumerable.from(second).forEach(function (key) { keys.add(key); });
1429
+ outs = new Dictionary(compareSelector);
1430
+ },
1431
+ function () {
1432
+ while (enumerator.moveNext()) {
1433
+ var current = enumerator.current();
1434
+ if (!outs.contains(current) && keys.contains(current)) {
1435
+ outs.add(current);
1436
+ return this.yieldReturn(current);
1437
+ }
1438
+ }
1439
+ return false;
1440
+ },
1441
+ function () { Utils.dispose(enumerator); });
1442
+ });
1443
+ };
1444
+
1445
+ // Overload:function(second)
1446
+ // Overload:function(second, compareSelector)
1447
+ Enumerable.prototype.sequenceEqual = function (second, compareSelector) {
1448
+ compareSelector = Utils.createLambda(compareSelector);
1449
+
1450
+ var firstEnumerator = this.getEnumerator();
1451
+ try {
1452
+ var secondEnumerator = Enumerable.from(second).getEnumerator();
1453
+ try {
1454
+ while (firstEnumerator.moveNext()) {
1455
+ if (!secondEnumerator.moveNext()
1456
+ || compareSelector(firstEnumerator.current()) !== compareSelector(secondEnumerator.current())) {
1457
+ return false;
1458
+ }
1459
+ }
1460
+
1461
+ if (secondEnumerator.moveNext()) return false;
1462
+ return true;
1463
+ }
1464
+ finally {
1465
+ Utils.dispose(secondEnumerator);
1466
+ }
1467
+ }
1468
+ finally {
1469
+ Utils.dispose(firstEnumerator);
1470
+ }
1471
+ };
1472
+
1473
+ Enumerable.prototype.union = function (second, compareSelector) {
1474
+ compareSelector = Utils.createLambda(compareSelector);
1475
+ var source = this;
1476
+
1477
+ return new Enumerable(function () {
1478
+ var firstEnumerator;
1479
+ var secondEnumerator;
1480
+ var keys;
1481
+
1482
+ return new IEnumerator(
1483
+ function () {
1484
+ firstEnumerator = source.getEnumerator();
1485
+ keys = new Dictionary(compareSelector);
1486
+ },
1487
+ function () {
1488
+ var current;
1489
+ if (secondEnumerator === undefined) {
1490
+ while (firstEnumerator.moveNext()) {
1491
+ current = firstEnumerator.current();
1492
+ if (!keys.contains(current)) {
1493
+ keys.add(current);
1494
+ return this.yieldReturn(current);
1495
+ }
1496
+ }
1497
+ secondEnumerator = Enumerable.from(second).getEnumerator();
1498
+ }
1499
+ while (secondEnumerator.moveNext()) {
1500
+ current = secondEnumerator.current();
1501
+ if (!keys.contains(current)) {
1502
+ keys.add(current);
1503
+ return this.yieldReturn(current);
1504
+ }
1505
+ }
1506
+ return false;
1507
+ },
1508
+ function () {
1509
+ try {
1510
+ Utils.dispose(firstEnumerator);
1511
+ }
1512
+ finally {
1513
+ Utils.dispose(secondEnumerator);
1514
+ }
1515
+ });
1516
+ });
1517
+ };
1518
+
1519
+ /* Ordering Methods */
1520
+
1521
+ Enumerable.prototype.orderBy = function (keySelector) {
1522
+ return new OrderedEnumerable(this, keySelector, false);
1523
+ };
1524
+
1525
+ Enumerable.prototype.orderByDescending = function (keySelector) {
1526
+ return new OrderedEnumerable(this, keySelector, true);
1527
+ };
1528
+
1529
+ Enumerable.prototype.reverse = function () {
1530
+ var source = this;
1531
+
1532
+ return new Enumerable(function () {
1533
+ var buffer;
1534
+ var index;
1535
+
1536
+ return new IEnumerator(
1537
+ function () {
1538
+ buffer = source.toArray();
1539
+ index = buffer.length;
1540
+ },
1541
+ function () {
1542
+ return (index > 0)
1543
+ ? this.yieldReturn(buffer[--index])
1544
+ : false;
1545
+ },
1546
+ Functions.Blank);
1547
+ });
1548
+ };
1549
+
1550
+ Enumerable.prototype.shuffle = function () {
1551
+ var source = this;
1552
+
1553
+ return new Enumerable(function () {
1554
+ var buffer;
1555
+
1556
+ return new IEnumerator(
1557
+ function () { buffer = source.toArray(); },
1558
+ function () {
1559
+ if (buffer.length > 0) {
1560
+ var i = Math.floor(Math.random() * buffer.length);
1561
+ return this.yieldReturn(buffer.splice(i, 1)[0]);
1562
+ }
1563
+ return false;
1564
+ },
1565
+ Functions.Blank);
1566
+ });
1567
+ };
1568
+
1569
+ Enumerable.prototype.weightedSample = function (weightSelector) {
1570
+ weightSelector = Utils.createLambda(weightSelector);
1571
+ var source = this;
1572
+
1573
+ return new Enumerable(function () {
1574
+ var sortedByBound;
1575
+ var totalWeight = 0;
1576
+
1577
+ return new IEnumerator(
1578
+ function () {
1579
+ sortedByBound = source
1580
+ .choose(function (x) {
1581
+ var weight = weightSelector(x);
1582
+ if (weight <= 0) return null; // ignore 0
1583
+
1584
+ totalWeight += weight;
1585
+ return { value: x, bound: totalWeight };
1586
+ })
1587
+ .toArray();
1588
+ },
1589
+ function () {
1590
+ if (sortedByBound.length > 0) {
1591
+ var draw = Math.floor(Math.random() * totalWeight) + 1;
1592
+
1593
+ var lower = -1;
1594
+ var upper = sortedByBound.length;
1595
+ while (upper - lower > 1) {
1596
+ var index = Math.floor((lower + upper) / 2);
1597
+ if (sortedByBound[index].bound >= draw) {
1598
+ upper = index;
1599
+ }
1600
+ else {
1601
+ lower = index;
1602
+ }
1603
+ }
1604
+
1605
+ return this.yieldReturn(sortedByBound[upper].value);
1606
+ }
1607
+
1608
+ return this.yieldBreak();
1609
+ },
1610
+ Functions.Blank);
1611
+ });
1612
+ };
1613
+
1614
+ /* Grouping Methods */
1615
+
1616
+ // Overload:function(keySelector)
1617
+ // Overload:function(keySelector,elementSelector)
1618
+ // Overload:function(keySelector,elementSelector,resultSelector)
1619
+ // Overload:function(keySelector,elementSelector,resultSelector,compareSelector)
1620
+ Enumerable.prototype.groupBy = function (keySelector, elementSelector, resultSelector, compareSelector) {
1621
+ var source = this;
1622
+ keySelector = Utils.createLambda(keySelector);
1623
+ elementSelector = Utils.createLambda(elementSelector);
1624
+ if (resultSelector != null) resultSelector = Utils.createLambda(resultSelector);
1625
+ compareSelector = Utils.createLambda(compareSelector);
1626
+
1627
+ return new Enumerable(function () {
1628
+ var enumerator;
1629
+
1630
+ return new IEnumerator(
1631
+ function () {
1632
+ enumerator = source.toLookup(keySelector, elementSelector, compareSelector)
1633
+ .toEnumerable()
1634
+ .getEnumerator();
1635
+ },
1636
+ function () {
1637
+ while (enumerator.moveNext()) {
1638
+ return (resultSelector == null)
1639
+ ? this.yieldReturn(enumerator.current())
1640
+ : this.yieldReturn(resultSelector(enumerator.current().key(), enumerator.current()));
1641
+ }
1642
+ return false;
1643
+ },
1644
+ function () { Utils.dispose(enumerator); });
1645
+ });
1646
+ };
1647
+
1648
+ // Overload:function(keySelector)
1649
+ // Overload:function(keySelector,elementSelector)
1650
+ // Overload:function(keySelector,elementSelector,resultSelector)
1651
+ // Overload:function(keySelector,elementSelector,resultSelector,compareSelector)
1652
+ Enumerable.prototype.partitionBy = function (keySelector, elementSelector, resultSelector, compareSelector) {
1653
+
1654
+ var source = this;
1655
+ keySelector = Utils.createLambda(keySelector);
1656
+ elementSelector = Utils.createLambda(elementSelector);
1657
+ compareSelector = Utils.createLambda(compareSelector);
1658
+ var hasResultSelector;
1659
+ if (resultSelector == null) {
1660
+ hasResultSelector = false;
1661
+ resultSelector = function (key, group) { return new Grouping(key, group); };
1662
+ }
1663
+ else {
1664
+ hasResultSelector = true;
1665
+ resultSelector = Utils.createLambda(resultSelector);
1666
+ }
1667
+
1668
+ return new Enumerable(function () {
1669
+ var enumerator;
1670
+ var key;
1671
+ var compareKey;
1672
+ var group = [];
1673
+
1674
+ return new IEnumerator(
1675
+ function () {
1676
+ enumerator = source.getEnumerator();
1677
+ if (enumerator.moveNext()) {
1678
+ key = keySelector(enumerator.current());
1679
+ compareKey = compareSelector(key);
1680
+ group.push(elementSelector(enumerator.current()));
1681
+ }
1682
+ },
1683
+ function () {
1684
+ var hasNext;
1685
+ while ((hasNext = enumerator.moveNext()) == true) {
1686
+ if (compareKey === compareSelector(keySelector(enumerator.current()))) {
1687
+ group.push(elementSelector(enumerator.current()));
1688
+ }
1689
+ else break;
1690
+ }
1691
+
1692
+ if (group.length > 0) {
1693
+ var result = (hasResultSelector)
1694
+ ? resultSelector(key, Enumerable.from(group))
1695
+ : resultSelector(key, group);
1696
+ if (hasNext) {
1697
+ key = keySelector(enumerator.current());
1698
+ compareKey = compareSelector(key);
1699
+ group = [elementSelector(enumerator.current())];
1700
+ }
1701
+ else group = [];
1702
+
1703
+ return this.yieldReturn(result);
1704
+ }
1705
+
1706
+ return false;
1707
+ },
1708
+ function () { Utils.dispose(enumerator); });
1709
+ });
1710
+ };
1711
+
1712
+ Enumerable.prototype.buffer = function (count) {
1713
+ var source = this;
1714
+
1715
+ return new Enumerable(function () {
1716
+ var enumerator;
1717
+
1718
+ return new IEnumerator(
1719
+ function () { enumerator = source.getEnumerator(); },
1720
+ function () {
1721
+ var array = [];
1722
+ var index = 0;
1723
+ while (enumerator.moveNext()) {
1724
+ array.push(enumerator.current());
1725
+ if (++index >= count) return this.yieldReturn(array);
1726
+ }
1727
+ if (array.length > 0) return this.yieldReturn(array);
1728
+ return false;
1729
+ },
1730
+ function () { Utils.dispose(enumerator); });
1731
+ });
1732
+ };
1733
+
1734
+ /* Aggregate Methods */
1735
+
1736
+ // Overload:function(func)
1737
+ // Overload:function(seed,func)
1738
+ // Overload:function(seed,func,resultSelector)
1739
+ Enumerable.prototype.aggregate = function (seed, func, resultSelector) {
1740
+ resultSelector = Utils.createLambda(resultSelector);
1741
+ return resultSelector(this.scan(seed, func, resultSelector).last());
1742
+ };
1743
+
1744
+ // Overload:function()
1745
+ // Overload:function(selector)
1746
+ Enumerable.prototype.average = function (selector) {
1747
+ selector = Utils.createLambda(selector);
1748
+
1749
+ var sum = 0;
1750
+ var count = 0;
1751
+ this.forEach(function (x) {
1752
+ sum += selector(x);
1753
+ ++count;
1754
+ });
1755
+
1756
+ return sum / count;
1757
+ };
1758
+
1759
+ // Overload:function()
1760
+ // Overload:function(predicate)
1761
+ Enumerable.prototype.count = function (predicate) {
1762
+ predicate = (predicate == null) ? Functions.True : Utils.createLambda(predicate);
1763
+
1764
+ var count = 0;
1765
+ this.forEach(function (x, i) {
1766
+ if (predicate(x, i))++count;
1767
+ });
1768
+ return count;
1769
+ };
1770
+
1771
+ // Overload:function()
1772
+ // Overload:function(selector)
1773
+ Enumerable.prototype.max = function (selector) {
1774
+ if (selector == null) selector = Functions.Identity;
1775
+ return this.select(selector).aggregate(function (a, b) { return (a > b) ? a : b; });
1776
+ };
1777
+
1778
+ // Overload:function()
1779
+ // Overload:function(selector)
1780
+ Enumerable.prototype.min = function (selector) {
1781
+ if (selector == null) selector = Functions.Identity;
1782
+ return this.select(selector).aggregate(function (a, b) { return (a < b) ? a : b; });
1783
+ };
1784
+
1785
+ Enumerable.prototype.maxBy = function (keySelector) {
1786
+ keySelector = Utils.createLambda(keySelector);
1787
+ return this.aggregate(function (a, b) { return (keySelector(a) > keySelector(b)) ? a : b; });
1788
+ };
1789
+
1790
+ Enumerable.prototype.minBy = function (keySelector) {
1791
+ keySelector = Utils.createLambda(keySelector);
1792
+ return this.aggregate(function (a, b) { return (keySelector(a) < keySelector(b)) ? a : b; });
1793
+ };
1794
+
1795
+ // Overload:function()
1796
+ // Overload:function(selector)
1797
+ Enumerable.prototype.sum = function (selector) {
1798
+ if (selector == null) selector = Functions.Identity;
1799
+ return this.select(selector).aggregate(0, function (a, b) { return a + b; });
1800
+ };
1801
+
1802
+ /* Paging Methods */
1803
+
1804
+ Enumerable.prototype.elementAt = function (index) {
1805
+ var value;
1806
+ var found = false;
1807
+ this.forEach(function (x, i) {
1808
+ if (i == index) {
1809
+ value = x;
1810
+ found = true;
1811
+ return false;
1812
+ }
1813
+ });
1814
+
1815
+ if (!found) throw new Error("index is less than 0 or greater than or equal to the number of elements in source.");
1816
+ return value;
1817
+ };
1818
+
1819
+ Enumerable.prototype.elementAtOrDefault = function (index, defaultValue) {
1820
+ if (defaultValue === undefined) defaultValue = null;
1821
+ var value;
1822
+ var found = false;
1823
+ this.forEach(function (x, i) {
1824
+ if (i == index) {
1825
+ value = x;
1826
+ found = true;
1827
+ return false;
1828
+ }
1829
+ });
1830
+
1831
+ return (!found) ? defaultValue : value;
1832
+ };
1833
+
1834
+ // Overload:function()
1835
+ // Overload:function(predicate)
1836
+ Enumerable.prototype.first = function (predicate) {
1837
+ if (predicate != null) return this.where(predicate).first();
1838
+
1839
+ var value;
1840
+ var found = false;
1841
+ this.forEach(function (x) {
1842
+ value = x;
1843
+ found = true;
1844
+ return false;
1845
+ });
1846
+
1847
+ if (!found) throw new Error("first:No element satisfies the condition.");
1848
+ return value;
1849
+ };
1850
+
1851
+ Enumerable.prototype.firstOrDefault = function (predicate, defaultValue) {
1852
+ if (defaultValue === undefined) defaultValue = null;
1853
+ if (predicate != null) return this.where(predicate).firstOrDefault(null, defaultValue);
1854
+
1855
+ var value;
1856
+ var found = false;
1857
+ this.forEach(function (x) {
1858
+ value = x;
1859
+ found = true;
1860
+ return false;
1861
+ });
1862
+ return (!found) ? defaultValue : value;
1863
+ };
1864
+
1865
+ // Overload:function()
1866
+ // Overload:function(predicate)
1867
+ Enumerable.prototype.last = function (predicate) {
1868
+ if (predicate != null) return this.where(predicate).last();
1869
+
1870
+ var value;
1871
+ var found = false;
1872
+ this.forEach(function (x) {
1873
+ found = true;
1874
+ value = x;
1875
+ });
1876
+
1877
+ if (!found) throw new Error("last:No element satisfies the condition.");
1878
+ return value;
1879
+ };
1880
+
1881
+ // Overload:function(defaultValue)
1882
+ // Overload:function(defaultValue,predicate)
1883
+ Enumerable.prototype.lastOrDefault = function (predicate, defaultValue) {
1884
+ if (defaultValue === undefined) defaultValue = null;
1885
+ if (predicate != null) return this.where(predicate).lastOrDefault(null, defaultValue);
1886
+
1887
+ var value;
1888
+ var found = false;
1889
+ this.forEach(function (x) {
1890
+ found = true;
1891
+ value = x;
1892
+ });
1893
+ return (!found) ? defaultValue : value;
1894
+ };
1895
+
1896
+ // Overload:function()
1897
+ // Overload:function(predicate)
1898
+ Enumerable.prototype.single = function (predicate) {
1899
+ if (predicate != null) return this.where(predicate).single();
1900
+
1901
+ var value;
1902
+ var found = false;
1903
+ this.forEach(function (x) {
1904
+ if (!found) {
1905
+ found = true;
1906
+ value = x;
1907
+ } else throw new Error("single:sequence contains more than one element.");
1908
+ });
1909
+
1910
+ if (!found) throw new Error("single:No element satisfies the condition.");
1911
+ return value;
1912
+ };
1913
+
1914
+ // Overload:function(defaultValue)
1915
+ // Overload:function(defaultValue,predicate)
1916
+ Enumerable.prototype.singleOrDefault = function (predicate, defaultValue) {
1917
+ if (defaultValue === undefined) defaultValue = null;
1918
+ if (predicate != null) return this.where(predicate).singleOrDefault(null, defaultValue);
1919
+
1920
+ var value;
1921
+ var found = false;
1922
+ this.forEach(function (x) {
1923
+ if (!found) {
1924
+ found = true;
1925
+ value = x;
1926
+ } else throw new Error("single:sequence contains more than one element.");
1927
+ });
1928
+
1929
+ return (!found) ? defaultValue : value;
1930
+ };
1931
+
1932
+ Enumerable.prototype.skip = function (count) {
1933
+ var source = this;
1934
+
1935
+ return new Enumerable(function () {
1936
+ var enumerator;
1937
+ var index = 0;
1938
+
1939
+ return new IEnumerator(
1940
+ function () {
1941
+ enumerator = source.getEnumerator();
1942
+ while (index++ < count && enumerator.moveNext()) {
1943
+ }
1944
+ ;
1945
+ },
1946
+ function () {
1947
+ return (enumerator.moveNext())
1948
+ ? this.yieldReturn(enumerator.current())
1949
+ : false;
1950
+ },
1951
+ function () { Utils.dispose(enumerator); });
1952
+ });
1953
+ };
1954
+
1955
+ // Overload:function(predicate<element>)
1956
+ // Overload:function(predicate<element,index>)
1957
+ Enumerable.prototype.skipWhile = function (predicate) {
1958
+ predicate = Utils.createLambda(predicate);
1959
+ var source = this;
1960
+
1961
+ return new Enumerable(function () {
1962
+ var enumerator;
1963
+ var index = 0;
1964
+ var isSkipEnd = false;
1965
+
1966
+ return new IEnumerator(
1967
+ function () { enumerator = source.getEnumerator(); },
1968
+ function () {
1969
+ while (!isSkipEnd) {
1970
+ if (enumerator.moveNext()) {
1971
+ if (!predicate(enumerator.current(), index++)) {
1972
+ isSkipEnd = true;
1973
+ return this.yieldReturn(enumerator.current());
1974
+ }
1975
+ continue;
1976
+ } else return false;
1977
+ }
1978
+
1979
+ return (enumerator.moveNext())
1980
+ ? this.yieldReturn(enumerator.current())
1981
+ : false;
1982
+
1983
+ },
1984
+ function () { Utils.dispose(enumerator); });
1985
+ });
1986
+ };
1987
+
1988
+ Enumerable.prototype.take = function (count) {
1989
+ var source = this;
1990
+
1991
+ return new Enumerable(function () {
1992
+ var enumerator;
1993
+ var index = 0;
1994
+
1995
+ return new IEnumerator(
1996
+ function () { enumerator = source.getEnumerator(); },
1997
+ function () {
1998
+ return (index++ < count && enumerator.moveNext())
1999
+ ? this.yieldReturn(enumerator.current())
2000
+ : false;
2001
+ },
2002
+ function () { Utils.dispose(enumerator); }
2003
+ );
2004
+ });
2005
+ };
2006
+
2007
+ // Overload:function(predicate<element>)
2008
+ // Overload:function(predicate<element,index>)
2009
+ Enumerable.prototype.takeWhile = function (predicate) {
2010
+ predicate = Utils.createLambda(predicate);
2011
+ var source = this;
2012
+
2013
+ return new Enumerable(function () {
2014
+ var enumerator;
2015
+ var index = 0;
2016
+
2017
+ return new IEnumerator(
2018
+ function () { enumerator = source.getEnumerator(); },
2019
+ function () {
2020
+ return (enumerator.moveNext() && predicate(enumerator.current(), index++))
2021
+ ? this.yieldReturn(enumerator.current())
2022
+ : false;
2023
+ },
2024
+ function () { Utils.dispose(enumerator); });
2025
+ });
2026
+ };
2027
+
2028
+ // Overload:function()
2029
+ // Overload:function(count)
2030
+ Enumerable.prototype.takeExceptLast = function (count) {
2031
+ if (count == null) count = 1;
2032
+ var source = this;
2033
+
2034
+ return new Enumerable(function () {
2035
+ if (count <= 0) return source.getEnumerator(); // do nothing
2036
+
2037
+ var enumerator;
2038
+ var q = [];
2039
+
2040
+ return new IEnumerator(
2041
+ function () { enumerator = source.getEnumerator(); },
2042
+ function () {
2043
+ while (enumerator.moveNext()) {
2044
+ if (q.length == count) {
2045
+ q.push(enumerator.current());
2046
+ return this.yieldReturn(q.shift());
2047
+ }
2048
+ q.push(enumerator.current());
2049
+ }
2050
+ return false;
2051
+ },
2052
+ function () { Utils.dispose(enumerator); });
2053
+ });
2054
+ };
2055
+
2056
+ Enumerable.prototype.takeFromLast = function (count) {
2057
+ if (count <= 0 || count == null) return Enumerable.empty();
2058
+ var source = this;
2059
+
2060
+ return new Enumerable(function () {
2061
+ var sourceEnumerator;
2062
+ var enumerator;
2063
+ var q = [];
2064
+
2065
+ return new IEnumerator(
2066
+ function () { sourceEnumerator = source.getEnumerator(); },
2067
+ function () {
2068
+ while (sourceEnumerator.moveNext()) {
2069
+ if (q.length == count) q.shift();
2070
+ q.push(sourceEnumerator.current());
2071
+ }
2072
+ if (enumerator == null) {
2073
+ enumerator = Enumerable.from(q).getEnumerator();
2074
+ }
2075
+ return (enumerator.moveNext())
2076
+ ? this.yieldReturn(enumerator.current())
2077
+ : false;
2078
+ },
2079
+ function () { Utils.dispose(enumerator); });
2080
+ });
2081
+ };
2082
+
2083
+ // Overload:function(item)
2084
+ // Overload:function(predicate)
2085
+ Enumerable.prototype.indexOf = function (item) {
2086
+ var found = null;
2087
+
2088
+ // item as predicate
2089
+ if (typeof (item) === Types.Function) {
2090
+ this.forEach(function (x, i) {
2091
+ if (item(x, i)) {
2092
+ found = i;
2093
+ return false;
2094
+ }
2095
+ });
2096
+ }
2097
+ else {
2098
+ this.forEach(function (x, i) {
2099
+ if (x === item) {
2100
+ found = i;
2101
+ return false;
2102
+ }
2103
+ });
2104
+ }
2105
+
2106
+ return (found !== null) ? found : -1;
2107
+ };
2108
+
2109
+ // Overload:function(item)
2110
+ // Overload:function(predicate)
2111
+ Enumerable.prototype.lastIndexOf = function (item) {
2112
+ var result = -1;
2113
+
2114
+ // item as predicate
2115
+ if (typeof (item) === Types.Function) {
2116
+ this.forEach(function (x, i) {
2117
+ if (item(x, i)) result = i;
2118
+ });
2119
+ }
2120
+ else {
2121
+ this.forEach(function (x, i) {
2122
+ if (x === item) result = i;
2123
+ });
2124
+ }
2125
+
2126
+ return result;
2127
+ };
2128
+
2129
+ /* Convert Methods */
2130
+
2131
+ Enumerable.prototype.asEnumerable = function () {
2132
+ return Enumerable.from(this);
2133
+ };
2134
+
2135
+ Enumerable.prototype.toArray = function () {
2136
+ var array = [];
2137
+ this.forEach(function (x) { array.push(x); });
2138
+ return array;
2139
+ };
2140
+
2141
+ // Overload:function(keySelector)
2142
+ // Overload:function(keySelector, elementSelector)
2143
+ // Overload:function(keySelector, elementSelector, compareSelector)
2144
+ Enumerable.prototype.toLookup = function (keySelector, elementSelector, compareSelector) {
2145
+ keySelector = Utils.createLambda(keySelector);
2146
+ elementSelector = Utils.createLambda(elementSelector);
2147
+ compareSelector = Utils.createLambda(compareSelector);
2148
+
2149
+ var dict = new Dictionary(compareSelector);
2150
+ this.forEach(function (x) {
2151
+ var key = keySelector(x);
2152
+ var element = elementSelector(x);
2153
+
2154
+ var array = dict.get(key);
2155
+ if (array !== undefined) array.push(element);
2156
+ else dict.add(key, [element]);
2157
+ });
2158
+ return new Lookup(dict);
2159
+ };
2160
+
2161
+ Enumerable.prototype.toObject = function (keySelector, elementSelector) {
2162
+ keySelector = Utils.createLambda(keySelector);
2163
+ elementSelector = Utils.createLambda(elementSelector);
2164
+
2165
+ var obj = {};
2166
+ this.forEach(function (x) {
2167
+ obj[keySelector(x)] = elementSelector(x);
2168
+ });
2169
+ return obj;
2170
+ };
2171
+
2172
+ // Overload:function(keySelector, elementSelector)
2173
+ // Overload:function(keySelector, elementSelector, compareSelector)
2174
+ Enumerable.prototype.toDictionary = function (keySelector, elementSelector, compareSelector) {
2175
+ keySelector = Utils.createLambda(keySelector);
2176
+ elementSelector = Utils.createLambda(elementSelector);
2177
+ compareSelector = Utils.createLambda(compareSelector);
2178
+
2179
+ var dict = new Dictionary(compareSelector);
2180
+ this.forEach(function (x) {
2181
+ dict.add(keySelector(x), elementSelector(x));
2182
+ });
2183
+ return dict;
2184
+ };
2185
+
2186
+ // Overload:function()
2187
+ // Overload:function(replacer)
2188
+ // Overload:function(replacer, space)
2189
+ Enumerable.prototype.toJSONString = function (replacer, space) {
2190
+ if (typeof JSON === Types.Undefined || JSON.stringify == null) {
2191
+ throw new Error("toJSONString can't find JSON.stringify. This works native JSON support Browser or include json2.js");
2192
+ }
2193
+ return JSON.stringify(this.toArray(), replacer, space);
2194
+ };
2195
+
2196
+ // Overload:function()
2197
+ // Overload:function(separator)
2198
+ // Overload:function(separator,selector)
2199
+ Enumerable.prototype.toJoinedString = function (separator, selector) {
2200
+ if (separator == null) separator = "";
2201
+ if (selector == null) selector = Functions.Identity;
2202
+
2203
+ return this.select(selector).toArray().join(separator);
2204
+ };
2205
+
2206
+
2207
+ /* Action Methods */
2208
+
2209
+ // Overload:function(action<element>)
2210
+ // Overload:function(action<element,index>)
2211
+ Enumerable.prototype.doAction = function (action) {
2212
+ var source = this;
2213
+ action = Utils.createLambda(action);
2214
+
2215
+ return new Enumerable(function () {
2216
+ var enumerator;
2217
+ var index = 0;
2218
+
2219
+ return new IEnumerator(
2220
+ function () { enumerator = source.getEnumerator(); },
2221
+ function () {
2222
+ if (enumerator.moveNext()) {
2223
+ action(enumerator.current(), index++);
2224
+ return this.yieldReturn(enumerator.current());
2225
+ }
2226
+ return false;
2227
+ },
2228
+ function () { Utils.dispose(enumerator); });
2229
+ });
2230
+ };
2231
+
2232
+ // Overload:function(action<element>)
2233
+ // Overload:function(action<element,index>)
2234
+ // Overload:function(func<element,bool>)
2235
+ // Overload:function(func<element,index,bool>)
2236
+ Enumerable.prototype.forEach = function (action) {
2237
+ action = Utils.createLambda(action);
2238
+
2239
+ var index = 0;
2240
+ var enumerator = this.getEnumerator();
2241
+ try {
2242
+ while (enumerator.moveNext()) {
2243
+ if (action(enumerator.current(), index++) === false) break;
2244
+ }
2245
+ } finally {
2246
+ Utils.dispose(enumerator);
2247
+ }
2248
+ };
2249
+
2250
+ // Overload:function()
2251
+ // Overload:function(separator)
2252
+ // Overload:function(separator,selector)
2253
+ Enumerable.prototype.write = function (separator, selector) {
2254
+ if (separator == null) separator = "";
2255
+ selector = Utils.createLambda(selector);
2256
+
2257
+ var isFirst = true;
2258
+ this.forEach(function (item) {
2259
+ if (isFirst) isFirst = false;
2260
+ else document.write(separator);
2261
+ document.write(selector(item));
2262
+ });
2263
+ };
2264
+
2265
+ // Overload:function()
2266
+ // Overload:function(selector)
2267
+ Enumerable.prototype.writeLine = function (selector) {
2268
+ selector = Utils.createLambda(selector);
2269
+
2270
+ this.forEach(function (item) {
2271
+ document.writeln(selector(item) + "<br />");
2272
+ });
2273
+ };
2274
+
2275
+ Enumerable.prototype.force = function () {
2276
+ var enumerator = this.getEnumerator();
2277
+
2278
+ try {
2279
+ while (enumerator.moveNext()) {
2280
+ }
2281
+ }
2282
+ finally {
2283
+ Utils.dispose(enumerator);
2284
+ }
2285
+ };
2286
+
2287
+ /* Functional Methods */
2288
+
2289
+ Enumerable.prototype.letBind = function (func) {
2290
+ func = Utils.createLambda(func);
2291
+ var source = this;
2292
+
2293
+ return new Enumerable(function () {
2294
+ var enumerator;
2295
+
2296
+ return new IEnumerator(
2297
+ function () {
2298
+ enumerator = Enumerable.from(func(source)).getEnumerator();
2299
+ },
2300
+ function () {
2301
+ return (enumerator.moveNext())
2302
+ ? this.yieldReturn(enumerator.current())
2303
+ : false;
2304
+ },
2305
+ function () { Utils.dispose(enumerator); });
2306
+ });
2307
+ };
2308
+
2309
+ Enumerable.prototype.share = function () {
2310
+ var source = this;
2311
+ var sharedEnumerator;
2312
+ var disposed = false;
2313
+
2314
+ return new DisposableEnumerable(function () {
2315
+ return new IEnumerator(
2316
+ function () {
2317
+ if (sharedEnumerator == null) {
2318
+ sharedEnumerator = source.getEnumerator();
2319
+ }
2320
+ },
2321
+ function () {
2322
+ if (disposed) throw new Error("enumerator is disposed");
2323
+
2324
+ return (sharedEnumerator.moveNext())
2325
+ ? this.yieldReturn(sharedEnumerator.current())
2326
+ : false;
2327
+ },
2328
+ Functions.Blank
2329
+ );
2330
+ }, function () {
2331
+ disposed = true;
2332
+ Utils.dispose(sharedEnumerator);
2333
+ });
2334
+ };
2335
+
2336
+ Enumerable.prototype.memoize = function () {
2337
+ var source = this;
2338
+ var cache;
2339
+ var enumerator;
2340
+ var disposed = false;
2341
+
2342
+ return new DisposableEnumerable(function () {
2343
+ var index = -1;
2344
+
2345
+ return new IEnumerator(
2346
+ function () {
2347
+ if (enumerator == null) {
2348
+ enumerator = source.getEnumerator();
2349
+ cache = [];
2350
+ }
2351
+ },
2352
+ function () {
2353
+ if (disposed) throw new Error("enumerator is disposed");
2354
+
2355
+ index++;
2356
+ if (cache.length <= index) {
2357
+ return (enumerator.moveNext())
2358
+ ? this.yieldReturn(cache[index] = enumerator.current())
2359
+ : false;
2360
+ }
2361
+
2362
+ return this.yieldReturn(cache[index]);
2363
+ },
2364
+ Functions.Blank
2365
+ );
2366
+ }, function () {
2367
+ disposed = true;
2368
+ Utils.dispose(enumerator);
2369
+ cache = null;
2370
+ });
2371
+ };
2372
+
2373
+ /* Error Handling Methods */
2374
+
2375
+ Enumerable.prototype.catchError = function (handler) {
2376
+ handler = Utils.createLambda(handler);
2377
+ var source = this;
2378
+
2379
+ return new Enumerable(function () {
2380
+ var enumerator;
2381
+
2382
+ return new IEnumerator(
2383
+ function () { enumerator = source.getEnumerator(); },
2384
+ function () {
2385
+ try {
2386
+ return (enumerator.moveNext())
2387
+ ? this.yieldReturn(enumerator.current())
2388
+ : false;
2389
+ } catch (e) {
2390
+ handler(e);
2391
+ return false;
2392
+ }
2393
+ },
2394
+ function () { Utils.dispose(enumerator); });
2395
+ });
2396
+ };
2397
+
2398
+ Enumerable.prototype.finallyAction = function (finallyAction) {
2399
+ finallyAction = Utils.createLambda(finallyAction);
2400
+ var source = this;
2401
+
2402
+ return new Enumerable(function () {
2403
+ var enumerator;
2404
+
2405
+ return new IEnumerator(
2406
+ function () { enumerator = source.getEnumerator(); },
2407
+ function () {
2408
+ return (enumerator.moveNext())
2409
+ ? this.yieldReturn(enumerator.current())
2410
+ : false;
2411
+ },
2412
+ function () {
2413
+ try {
2414
+ Utils.dispose(enumerator);
2415
+ } finally {
2416
+ finallyAction();
2417
+ }
2418
+ });
2419
+ });
2420
+ };
2421
+
2422
+ /* For Debug Methods */
2423
+
2424
+ // Overload:function()
2425
+ // Overload:function(selector)
2426
+ Enumerable.prototype.log = function (selector) {
2427
+ selector = Utils.createLambda(selector);
2428
+
2429
+ return this.doAction(function (item) {
2430
+ if (typeof console !== Types.Undefined) {
2431
+ console.log(selector(item));
2432
+ }
2433
+ });
2434
+ };
2435
+
2436
+ // Overload:function()
2437
+ // Overload:function(message)
2438
+ // Overload:function(message,selector)
2439
+ Enumerable.prototype.trace = function (message, selector) {
2440
+ if (message == null) message = "Trace";
2441
+ selector = Utils.createLambda(selector);
2442
+
2443
+ return this.doAction(function (item) {
2444
+ if (typeof console !== Types.Undefined) {
2445
+ console.log(message, selector(item));
2446
+ }
2447
+ });
2448
+ };
2449
+
2450
+ // private
2451
+
2452
+ var OrderedEnumerable = function (source, keySelector, descending, parent) {
2453
+ this.source = source;
2454
+ this.keySelector = Utils.createLambda(keySelector);
2455
+ this.descending = descending;
2456
+ this.parent = parent;
2457
+ };
2458
+ OrderedEnumerable.prototype = new Enumerable();
2459
+
2460
+ OrderedEnumerable.prototype.createOrderedEnumerable = function (keySelector, descending) {
2461
+ return new OrderedEnumerable(this.source, keySelector, descending, this);
2462
+ };
2463
+ OrderedEnumerable.prototype.thenBy = function (keySelector) {
2464
+ return this.createOrderedEnumerable(keySelector, false);
2465
+ };
2466
+ OrderedEnumerable.prototype.thenByDescending = function (keySelector) {
2467
+ return this.createOrderedEnumerable(keySelector, true);
2468
+ };
2469
+ OrderedEnumerable.prototype.getEnumerator = function () {
2470
+ var self = this;
2471
+ var buffer;
2472
+ var indexes;
2473
+ var index = 0;
2474
+
2475
+ return new IEnumerator(
2476
+ function () {
2477
+ buffer = [];
2478
+ indexes = [];
2479
+ self.source.forEach(function (item, index) {
2480
+ buffer.push(item);
2481
+ indexes.push(index);
2482
+ });
2483
+ var sortContext = SortContext.create(self, null);
2484
+ sortContext.GenerateKeys(buffer);
2485
+
2486
+ indexes.sort(function (a, b) { return sortContext.compare(a, b); });
2487
+ },
2488
+ function () {
2489
+ return (index < indexes.length)
2490
+ ? this.yieldReturn(buffer[indexes[index++]])
2491
+ : false;
2492
+ },
2493
+ Functions.Blank
2494
+ );
2495
+ };
2496
+
2497
+ var SortContext = function (keySelector, descending, child) {
2498
+ this.keySelector = keySelector;
2499
+ this.descending = descending;
2500
+ this.child = child;
2501
+ this.keys = null;
2502
+ };
2503
+ SortContext.create = function (orderedEnumerable, currentContext) {
2504
+ var context = new SortContext(orderedEnumerable.keySelector, orderedEnumerable.descending, currentContext);
2505
+ if (orderedEnumerable.parent != null) return SortContext.create(orderedEnumerable.parent, context);
2506
+ return context;
2507
+ };
2508
+ SortContext.prototype.GenerateKeys = function (source) {
2509
+ var len = source.length;
2510
+ var keySelector = this.keySelector;
2511
+ var keys = new Array(len);
2512
+ for (var i = 0; i < len; i++) keys[i] = keySelector(source[i]);
2513
+ this.keys = keys;
2514
+
2515
+ if (this.child != null) this.child.GenerateKeys(source);
2516
+ };
2517
+ SortContext.prototype.compare = function (index1, index2) {
2518
+ var comparison = Utils.compare(this.keys[index1], this.keys[index2]);
2519
+
2520
+ if (comparison == 0) {
2521
+ if (this.child != null) return this.child.compare(index1, index2);
2522
+ return Utils.compare(index1, index2);
2523
+ }
2524
+
2525
+ return (this.descending) ? -comparison : comparison;
2526
+ };
2527
+
2528
+ var DisposableEnumerable = function (getEnumerator, dispose) {
2529
+ this.dispose = dispose;
2530
+ Enumerable.call(this, getEnumerator);
2531
+ };
2532
+ DisposableEnumerable.prototype = new Enumerable();
2533
+
2534
+ // optimize array or arraylike object
2535
+
2536
+ var ArrayEnumerable = function (source) {
2537
+ this.getSource = function () { return source; };
2538
+ };
2539
+ ArrayEnumerable.prototype = new Enumerable();
2540
+
2541
+ ArrayEnumerable.prototype.any = function (predicate) {
2542
+ return (predicate == null)
2543
+ ? (this.getSource().length > 0)
2544
+ : Enumerable.prototype.any.apply(this, arguments);
2545
+ };
2546
+
2547
+ ArrayEnumerable.prototype.count = function (predicate) {
2548
+ return (predicate == null)
2549
+ ? this.getSource().length
2550
+ : Enumerable.prototype.count.apply(this, arguments);
2551
+ };
2552
+
2553
+ ArrayEnumerable.prototype.elementAt = function (index) {
2554
+ var source = this.getSource();
2555
+ return (0 <= index && index < source.length)
2556
+ ? source[index]
2557
+ : Enumerable.prototype.elementAt.apply(this, arguments);
2558
+ };
2559
+
2560
+ ArrayEnumerable.prototype.elementAtOrDefault = function (index, defaultValue) {
2561
+ if (defaultValue === undefined) defaultValue = null;
2562
+ var source = this.getSource();
2563
+ return (0 <= index && index < source.length)
2564
+ ? source[index]
2565
+ : defaultValue;
2566
+ };
2567
+
2568
+ ArrayEnumerable.prototype.first = function (predicate) {
2569
+ var source = this.getSource();
2570
+ return (predicate == null && source.length > 0)
2571
+ ? source[0]
2572
+ : Enumerable.prototype.first.apply(this, arguments);
2573
+ };
2574
+
2575
+ ArrayEnumerable.prototype.firstOrDefault = function (predicate, defaultValue) {
2576
+ if (defaultValue === undefined) defaultValue = null;
2577
+ if (predicate != null) {
2578
+ return Enumerable.prototype.firstOrDefault.apply(this, arguments);
2579
+ }
2580
+
2581
+ var source = this.getSource();
2582
+ return source.length > 0 ? source[0] : defaultValue;
2583
+ };
2584
+
2585
+ ArrayEnumerable.prototype.last = function (predicate) {
2586
+ var source = this.getSource();
2587
+ return (predicate == null && source.length > 0)
2588
+ ? source[source.length - 1]
2589
+ : Enumerable.prototype.last.apply(this, arguments);
2590
+ };
2591
+
2592
+ ArrayEnumerable.prototype.lastOrDefault = function (predicate, defaultValue) {
2593
+ if (defaultValue === undefined) defaultValue = null;
2594
+ if (predicate != null) {
2595
+ return Enumerable.prototype.lastOrDefault.apply(this, arguments);
2596
+ }
2597
+
2598
+ var source = this.getSource();
2599
+ return source.length > 0 ? source[source.length - 1] : defaultValue;
2600
+ };
2601
+
2602
+ ArrayEnumerable.prototype.skip = function (count) {
2603
+ var source = this.getSource();
2604
+
2605
+ return new Enumerable(function () {
2606
+ var index;
2607
+
2608
+ return new IEnumerator(
2609
+ function () { index = (count < 0) ? 0 : count; },
2610
+ function () {
2611
+ return (index < source.length)
2612
+ ? this.yieldReturn(source[index++])
2613
+ : false;
2614
+ },
2615
+ Functions.Blank);
2616
+ });
2617
+ };
2618
+
2619
+ ArrayEnumerable.prototype.takeExceptLast = function (count) {
2620
+ if (count == null) count = 1;
2621
+ return this.take(this.getSource().length - count);
2622
+ };
2623
+
2624
+ ArrayEnumerable.prototype.takeFromLast = function (count) {
2625
+ return this.skip(this.getSource().length - count);
2626
+ };
2627
+
2628
+ ArrayEnumerable.prototype.reverse = function () {
2629
+ var source = this.getSource();
2630
+
2631
+ return new Enumerable(function () {
2632
+ var index;
2633
+
2634
+ return new IEnumerator(
2635
+ function () {
2636
+ index = source.length;
2637
+ },
2638
+ function () {
2639
+ return (index > 0)
2640
+ ? this.yieldReturn(source[--index])
2641
+ : false;
2642
+ },
2643
+ Functions.Blank);
2644
+ });
2645
+ };
2646
+
2647
+ ArrayEnumerable.prototype.sequenceEqual = function (second, compareSelector) {
2648
+ if ((second instanceof ArrayEnumerable || second instanceof Array)
2649
+ && compareSelector == null
2650
+ && Enumerable.from(second).count() != this.count()) {
2651
+ return false;
2652
+ }
2653
+
2654
+ return Enumerable.prototype.sequenceEqual.apply(this, arguments);
2655
+ };
2656
+
2657
+ ArrayEnumerable.prototype.toJoinedString = function (separator, selector) {
2658
+ var source = this.getSource();
2659
+ if (selector != null || !(source instanceof Array)) {
2660
+ return Enumerable.prototype.toJoinedString.apply(this, arguments);
2661
+ }
2662
+
2663
+ if (separator == null) separator = "";
2664
+ return source.join(separator);
2665
+ };
2666
+
2667
+ ArrayEnumerable.prototype.getEnumerator = function () {
2668
+ var source = this.getSource();
2669
+ var index = -1;
2670
+
2671
+ // fast and simple enumerator
2672
+ return {
2673
+ current: function () { return source[index]; },
2674
+ moveNext: function () {
2675
+ return ++index < source.length;
2676
+ },
2677
+ dispose: Functions.Blank
2678
+ };
2679
+ };
2680
+
2681
+ // optimization for multiple where and multiple select and whereselect
2682
+
2683
+ var WhereEnumerable = function (source, predicate) {
2684
+ this.prevSource = source;
2685
+ this.prevPredicate = predicate; // predicate.length always <= 1
2686
+ };
2687
+ WhereEnumerable.prototype = new Enumerable();
2688
+
2689
+ WhereEnumerable.prototype.where = function (predicate) {
2690
+ predicate = Utils.createLambda(predicate);
2691
+
2692
+ if (predicate.length <= 1) {
2693
+ var prevPredicate = this.prevPredicate;
2694
+ var composedPredicate = function (x) { return prevPredicate(x) && predicate(x); };
2695
+ return new WhereEnumerable(this.prevSource, composedPredicate);
2696
+ }
2697
+ else {
2698
+ // if predicate use index, can't compose
2699
+ return Enumerable.prototype.where.call(this, predicate);
2700
+ }
2701
+ };
2702
+
2703
+ WhereEnumerable.prototype.select = function (selector) {
2704
+ selector = Utils.createLambda(selector);
2705
+
2706
+ return (selector.length <= 1)
2707
+ ? new WhereSelectEnumerable(this.prevSource, this.prevPredicate, selector)
2708
+ : Enumerable.prototype.select.call(this, selector);
2709
+ };
2710
+
2711
+ WhereEnumerable.prototype.getEnumerator = function () {
2712
+ var predicate = this.prevPredicate;
2713
+ var source = this.prevSource;
2714
+ var enumerator;
2715
+
2716
+ return new IEnumerator(
2717
+ function () { enumerator = source.getEnumerator(); },
2718
+ function () {
2719
+ while (enumerator.moveNext()) {
2720
+ if (predicate(enumerator.current())) {
2721
+ return this.yieldReturn(enumerator.current());
2722
+ }
2723
+ }
2724
+ return false;
2725
+ },
2726
+ function () { Utils.dispose(enumerator); });
2727
+ };
2728
+
2729
+ var WhereSelectEnumerable = function (source, predicate, selector) {
2730
+ this.prevSource = source;
2731
+ this.prevPredicate = predicate; // predicate.length always <= 1 or null
2732
+ this.prevSelector = selector; // selector.length always <= 1
2733
+ };
2734
+ WhereSelectEnumerable.prototype = new Enumerable();
2735
+
2736
+ WhereSelectEnumerable.prototype.where = function (predicate) {
2737
+ predicate = Utils.createLambda(predicate);
2738
+
2739
+ return (predicate.length <= 1)
2740
+ ? new WhereEnumerable(this, predicate)
2741
+ : Enumerable.prototype.where.call(this, predicate);
2742
+ };
2743
+
2744
+ WhereSelectEnumerable.prototype.select = function (selector) {
2745
+ selector = Utils.createLambda(selector);
2746
+
2747
+ if (selector.length <= 1) {
2748
+ var prevSelector = this.prevSelector;
2749
+ var composedSelector = function (x) { return selector(prevSelector(x)); };
2750
+ return new WhereSelectEnumerable(this.prevSource, this.prevPredicate, composedSelector);
2751
+ }
2752
+ else {
2753
+ // if selector use index, can't compose
2754
+ return Enumerable.prototype.select.call(this, selector);
2755
+ }
2756
+ };
2757
+
2758
+ WhereSelectEnumerable.prototype.getEnumerator = function () {
2759
+ var predicate = this.prevPredicate;
2760
+ var selector = this.prevSelector;
2761
+ var source = this.prevSource;
2762
+ var enumerator;
2763
+
2764
+ return new IEnumerator(
2765
+ function () { enumerator = source.getEnumerator(); },
2766
+ function () {
2767
+ while (enumerator.moveNext()) {
2768
+ if (predicate == null || predicate(enumerator.current())) {
2769
+ return this.yieldReturn(selector(enumerator.current()));
2770
+ }
2771
+ }
2772
+ return false;
2773
+ },
2774
+ function () { Utils.dispose(enumerator); });
2775
+ };
2776
+
2777
+ // Collections
2778
+
2779
+ var Dictionary = (function () {
2780
+ // static utility methods
2781
+ var callHasOwnProperty = function (target, key) {
2782
+ return Object.prototype.hasOwnProperty.call(target, key);
2783
+ };
2784
+
2785
+ var computeHashCode = function (obj) {
2786
+ if (obj === null) return "null";
2787
+ if (obj === undefined) return "undefined";
2788
+
2789
+ return (typeof obj.toString === Types.Function)
2790
+ ? obj.toString()
2791
+ : Object.prototype.toString.call(obj);
2792
+ };
2793
+
2794
+ // LinkedList for Dictionary
2795
+ var HashEntry = function (key, value) {
2796
+ this.key = key;
2797
+ this.value = value;
2798
+ this.prev = null;
2799
+ this.next = null;
2800
+ };
2801
+
2802
+ var EntryList = function () {
2803
+ this.first = null;
2804
+ this.last = null;
2805
+ };
2806
+ EntryList.prototype =
2807
+ {
2808
+ addLast: function (entry) {
2809
+ if (this.last != null) {
2810
+ this.last.next = entry;
2811
+ entry.prev = this.last;
2812
+ this.last = entry;
2813
+ } else this.first = this.last = entry;
2814
+ },
2815
+
2816
+ replace: function (entry, newEntry) {
2817
+ if (entry.prev != null) {
2818
+ entry.prev.next = newEntry;
2819
+ newEntry.prev = entry.prev;
2820
+ } else this.first = newEntry;
2821
+
2822
+ if (entry.next != null) {
2823
+ entry.next.prev = newEntry;
2824
+ newEntry.next = entry.next;
2825
+ } else this.last = newEntry;
2826
+
2827
+ },
2828
+
2829
+ remove: function (entry) {
2830
+ if (entry.prev != null) entry.prev.next = entry.next;
2831
+ else this.first = entry.next;
2832
+
2833
+ if (entry.next != null) entry.next.prev = entry.prev;
2834
+ else this.last = entry.prev;
2835
+ }
2836
+ };
2837
+
2838
+ // Overload:function()
2839
+ // Overload:function(compareSelector)
2840
+ var Dictionary = function (compareSelector) {
2841
+ this.countField = 0;
2842
+ this.entryList = new EntryList();
2843
+ this.buckets = {}; // as Dictionary<string,List<object>>
2844
+ this.compareSelector = (compareSelector == null) ? Functions.Identity : compareSelector;
2845
+ };
2846
+ Dictionary.prototype =
2847
+ {
2848
+ add: function (key, value) {
2849
+ var compareKey = this.compareSelector(key);
2850
+ var hash = computeHashCode(compareKey);
2851
+ var entry = new HashEntry(key, value);
2852
+ if (callHasOwnProperty(this.buckets, hash)) {
2853
+ var array = this.buckets[hash];
2854
+ for (var i = 0; i < array.length; i++) {
2855
+ if (this.compareSelector(array[i].key) === compareKey) {
2856
+ this.entryList.replace(array[i], entry);
2857
+ array[i] = entry;
2858
+ return;
2859
+ }
2860
+ }
2861
+ array.push(entry);
2862
+ } else {
2863
+ this.buckets[hash] = [entry];
2864
+ }
2865
+ this.countField++;
2866
+ this.entryList.addLast(entry);
2867
+ },
2868
+
2869
+ get: function (key) {
2870
+ var compareKey = this.compareSelector(key);
2871
+ var hash = computeHashCode(compareKey);
2872
+ if (!callHasOwnProperty(this.buckets, hash)) return undefined;
2873
+
2874
+ var array = this.buckets[hash];
2875
+ for (var i = 0; i < array.length; i++) {
2876
+ var entry = array[i];
2877
+ if (this.compareSelector(entry.key) === compareKey) return entry.value;
2878
+ }
2879
+ return undefined;
2880
+ },
2881
+
2882
+ set: function (key, value) {
2883
+ var compareKey = this.compareSelector(key);
2884
+ var hash = computeHashCode(compareKey);
2885
+ if (callHasOwnProperty(this.buckets, hash)) {
2886
+ var array = this.buckets[hash];
2887
+ for (var i = 0; i < array.length; i++) {
2888
+ if (this.compareSelector(array[i].key) === compareKey) {
2889
+ var newEntry = new HashEntry(key, value);
2890
+ this.entryList.replace(array[i], newEntry);
2891
+ array[i] = newEntry;
2892
+ return true;
2893
+ }
2894
+ }
2895
+ }
2896
+ return false;
2897
+ },
2898
+
2899
+ contains: function (key) {
2900
+ var compareKey = this.compareSelector(key);
2901
+ var hash = computeHashCode(compareKey);
2902
+ if (!callHasOwnProperty(this.buckets, hash)) return false;
2903
+
2904
+ var array = this.buckets[hash];
2905
+ for (var i = 0; i < array.length; i++) {
2906
+ if (this.compareSelector(array[i].key) === compareKey) return true;
2907
+ }
2908
+ return false;
2909
+ },
2910
+
2911
+ clear: function () {
2912
+ this.countField = 0;
2913
+ this.buckets = {};
2914
+ this.entryList = new EntryList();
2915
+ },
2916
+
2917
+ remove: function (key) {
2918
+ var compareKey = this.compareSelector(key);
2919
+ var hash = computeHashCode(compareKey);
2920
+ if (!callHasOwnProperty(this.buckets, hash)) return;
2921
+
2922
+ var array = this.buckets[hash];
2923
+ for (var i = 0; i < array.length; i++) {
2924
+ if (this.compareSelector(array[i].key) === compareKey) {
2925
+ this.entryList.remove(array[i]);
2926
+ array.splice(i, 1);
2927
+ if (array.length == 0) delete this.buckets[hash];
2928
+ this.countField--;
2929
+ return;
2930
+ }
2931
+ }
2932
+ },
2933
+
2934
+ count: function () {
2935
+ return this.countField;
2936
+ },
2937
+
2938
+ toEnumerable: function () {
2939
+ var self = this;
2940
+ return new Enumerable(function () {
2941
+ var currentEntry;
2942
+
2943
+ return new IEnumerator(
2944
+ function () { currentEntry = self.entryList.first; },
2945
+ function () {
2946
+ if (currentEntry != null) {
2947
+ var result = { key: currentEntry.key, value: currentEntry.value };
2948
+ currentEntry = currentEntry.next;
2949
+ return this.yieldReturn(result);
2950
+ }
2951
+ return false;
2952
+ },
2953
+ Functions.Blank);
2954
+ });
2955
+ }
2956
+ };
2957
+
2958
+ return Dictionary;
2959
+ })();
2960
+
2961
+ // dictionary = Dictionary<TKey, TValue[]>
2962
+ var Lookup = function (dictionary) {
2963
+ this.count = function () {
2964
+ return dictionary.count();
2965
+ };
2966
+ this.get = function (key) {
2967
+ return Enumerable.from(dictionary.get(key));
2968
+ };
2969
+ this.contains = function (key) {
2970
+ return dictionary.contains(key);
2971
+ };
2972
+ this.toEnumerable = function () {
2973
+ return dictionary.toEnumerable().select(function (kvp) {
2974
+ return new Grouping(kvp.key, kvp.value);
2975
+ });
2976
+ };
2977
+ };
2978
+
2979
+ var Grouping = function (groupKey, elements) {
2980
+ this.key = function () {
2981
+ return groupKey;
2982
+ };
2983
+ ArrayEnumerable.call(this, elements);
2984
+ };
2985
+ Grouping.prototype = new ArrayEnumerable();
2986
+
2987
+ // module export
2988
+ if (typeof define === Types.Function && define.amd) { // AMD
2989
+ define("linqjs", [], function () { return Enumerable; });
2990
+ }
2991
+ else if (typeof module !== Types.Undefined && module.exports) { // Node
2992
+ module.exports = Enumerable;
2993
+ }
2994
+ else {
2995
+ root.Enumerable = Enumerable;
2996
+ }
2997
+ })(this);