linq 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);