1/*-------------------------------------------------------------------------- 2* linq.js - LINQ for JavaScript 3* ver 2.2.0.2 (Jan. 21th, 2011) 4* 5* created and maintained by neuecc <[email protected]> 6* licensed under Microsoft Public License(Ms-PL) 7* http://neue.cc/ 8* http://linqjs.codeplex.com/ 9*--------------------------------------------------------------------------*/ 10 11Enumerable = (function () 12{ 13 var Enumerable = function (getEnumerator) 14 { 15 this.GetEnumerator = getEnumerator; 16 } 17 18 // Generator 19 20 Enumerable.Choice = function () // variable argument 21 { 22 var args = (arguments[0] instanceof Array) ? arguments[0] : arguments; 23 24 return new Enumerable(function () 25 { 26 return new IEnumerator( 27 Functions.Blank, 28 function () 29 { 30 return this.Yield(args[Math.floor(Math.random() * args.length)]); 31 }, 32 Functions.Blank); 33 }); 34 } 35 36 Enumerable.Cycle = function () // variable argument 37 { 38 var args = (arguments[0] instanceof Array) ? arguments[0] : arguments; 39 40 return new Enumerable(function () 41 { 42 var index = 0; 43 return new IEnumerator( 44 Functions.Blank, 45 function () 46 { 47 if (index >= args.length) index = 0; 48 return this.Yield(args[index++]); 49 }, 50 Functions.Blank); 51 }); 52 } 53 54 Enumerable.Empty = function () 55 { 56 return new Enumerable(function () 57 { 58 return new IEnumerator( 59 Functions.Blank, 60 function () { return false; }, 61 Functions.Blank); 62 }); 63 } 64 65 Enumerable.From = function (obj) 66 { 67 if (obj == null) 68 { 69 return Enumerable.Empty(); 70 } 71 if (obj instanceof Enumerable) 72 { 73 return obj; 74 } 75 if (typeof obj == Types.Number || typeof obj == Types.Boolean) 76 { 77 return Enumerable.Repeat(obj, 1); 78 } 79 if (typeof obj == Types.String) 80 { 81 return new Enumerable(function () 82 { 83 var index = 0; 84 return new IEnumerator( 85 Functions.Blank, 86 function () 87 { 88 return (index < obj.length) ? this.Yield(obj.charAt(index++)) : false; 89 }, 90 Functions.Blank); 91 }); 92 } 93 if (typeof obj != Types.Function) 94 { 95 // array or array like object 96 if (typeof obj.length == Types.Number) 97 { 98 return new ArrayEnumerable(obj); 99 } 100 101 // JScript's IEnumerable 102 if (!(obj instanceof Object) && Utils.IsIEnumerable(obj)) 103 { 104 return new Enumerable(function () 105 { 106 var isFirst = true; 107 var enumerator; 108 return new IEnumerator( 109 function () { enumerator = new Enumerator(obj); }, 110 function () 111 { 112 if (isFirst) isFirst = false; 113 else enumerator.moveNext(); 114 115 return (enumerator.atEnd()) ? false : this.Yield(enumerator.item()); 116 }, 117 Functions.Blank); 118 }); 119 } 120 } 121 122 // case function/object : Create KeyValuePair[] 123 return new Enumerable(function () 124 { 125 var array = []; 126 var index = 0; 127 128 return new IEnumerator( 129 function () 130 { 131 for (var key in obj) 132 { 133 if (!(obj[key] instanceof Function)) 134 { 135 array.push({ Key: key, Value: obj[key] }); 136 } 137 } 138 }, 139 function () 140 { 141 return (index < array.length) 142 ? this.Yield(array[index++]) 143 : false; 144 }, 145 Functions.Blank); 146 }); 147 }, 148 149 Enumerable.Return = function (element) 150 { 151 return Enumerable.Repeat(element, 1); 152 } 153 154 // Overload:function(input, pattern) 155 // Overload:function(input, pattern, flags) 156 Enumerable.Matches = function (input, pattern, flags) 157 { 158 if (flags == null) flags = ""; 159 if (pattern instanceof RegExp) 160 { 161 flags += (pattern.ignoreCase) ? "i" : ""; 162 flags += (pattern.multiline) ? "m" : ""; 163 pattern = pattern.source; 164 } 165 if (flags.indexOf("g") === -1) flags += "g"; 166 167 return new Enumerable(function () 168 { 169 var regex; 170 return new IEnumerator( 171 function () { regex = new RegExp(pattern, flags) }, 172 function () 173 { 174 var match = regex.exec(input); 175 return (match) ? this.Yield(match) : false; 176 }, 177 Functions.Blank); 178 }); 179 } 180 181 // Overload:function(start, count) 182 // Overload:function(start, count, step) 183 Enumerable.Range = function (start, count, step) 184 {
185 if (step == null) step = 1; 186 return Enumerable.ToInfinity(start, step).Take(count); 187 } 188 189 // Overload:function(start, count) 190 // Overload:function(start, count, step) 191 Enumerable.RangeDown = function (start, count, step) 192 { 193 if (step == null) step = 1; 194 return Enumerable.ToNegativeInfinity(start, step).Take(count); 195 } 196 197 // Overload:function(start, to) 198 // Overload:function(start, to, step) 199 Enumerable.RangeTo = function (start, to, step) 200 { 201 if (step == null) step = 1; 202 return (start < to) 203 ? Enumerable.ToInfinity(start, step).TakeWhile(function (i) { return i <= to; }) 204 : Enumerable.ToNegativeInfinity(start, step).TakeWhile(function (i) { return i >= to; }) 205 } 206 207 // Overload:function(obj) 208 // Overload:function(obj, num) 209 Enumerable.Repeat = function (obj, num) 210 { 211 if (num != null) return Enumerable.Repeat(obj).Take(num); 212 213 return new Enumerable(function () 214 { 215 return new IEnumerator( 216 Functions.Blank, 217 function () { return this.Yield(obj); }, 218 Functions.Blank); 219 }); 220 } 221 222 Enumerable.RepeatWithFinalize = function (initializer, finalizer) 223 { 224 initializer = Utils.CreateLambda(initializer); 225 finalizer = Utils.CreateLambda(finalizer); 226 227 return new Enumerable(function () 228 { 229 var element; 230 return new IEnumerator( 231 function () { element = initializer(); }, 232 function () { return this.Yield(element); }, 233 function () 234 { 235 if (element != null) 236 { 237 finalizer(element); 238 element = null; 239 } 240 }); 241 }); 242 } 243 244 // Overload:function(func) 245 // Overload:function(func, count) 246 Enumerable.Generate = function (func, count) 247 { 248 if (count != null) return Enumerable.Generate(func).Take(count); 249 func = Utils.CreateLambda(func); 250 251 return new Enumerable(function () 252 { 253 return new IEnumerator( 254 Functions.Blank, 255 function () { return this.Yield(func()); }, 256 Functions.Blank); 257 }); 258 } 259 260 // Overload:function() 261 // Overload:function(start) 262 // Overload:function(start, step) 263 Enumerable.ToInfinity = function (start, step) 264 { 265 if (start == null) start = 0; 266 if (step == null) step = 1; 267 268 return new Enumerable(function () 269 { 270 var value; 271 return new IEnumerator( 272 function () { value = start - step }, 273 function () { return this.Yield(value += step); }, 274 Functions.Blank); 275 }); 276 } 277 278 // Overload:function() 279 // Overload:function(start) 280 // Overload:function(start, step) 281 Enumerable.ToNegativeInfinity = function (start, step) 282 { 283 if (start == null) start = 0; 284 if (step == null) step = 1; 285 286 return new Enumerable(function () 287 { 288 var value; 289 return new IEnumerator( 290 function () { value = start + step }, 291 function () { return this.Yield(value -= step); }, 292 Functions.Blank); 293 }); 294 } 295 296 Enumerable.Unfold = function (seed, func) 297 { 298 func = Utils.CreateLambda(func); 299 300 return new Enumerable(function () 301 { 302 var isFirst = true; 303 var value; 304 return new IEnumerator( 305 Functions.Blank, 306 function () 307 { 308 if (isFirst) 309 { 310 isFirst = false; 311 value = seed; 312 return this.Yield(value); 313 } 314 value = func(value); 315 return this.Yield(value); 316 }, 317 Functions.Blank); 318 }); 319 } 320 321 // Extension Methods 322 323 Enumerable.prototype = 324 { 325 /* Projection and Filtering Methods */ 326 327 // Overload:function(func) 328 // Overload:function(func, resultSelector<element>) 329 // Overload:function(func, resultSelector<element, nestLevel>) 330 CascadeBreadthFirst: function (func, resultSelector) 331 { 332 var source = this; 333 func = Utils.CreateLambda(func); 334 resultSelector = Utils.CreateLambda(resultSelector); 335 336 return new Enumerable(function () 337 { 338 var enumerator; 339 var nestLevel = 0; 340 var buffer = []; 341 342 return new IEnumerator( 343 function () { enumerator = source.GetEnumerator(); }, 344 function () 345 { 346 while (true) 347 { 348 if (enumerator.MoveNext()) 349 { 350 buffer.push(enumerator.Current()); 351 return this.Yield(resultSelector(enumerator.Current(), nestLevel)); 352 } 353 354 var next = Enumerable.From(buffer).SelectMany(function (x) { return func(x); }); 355 if (!next.Any()) 356 { 357 return false; 358 } 359 else 360 { 361 nestLevel++; 362 buffer = []; 363 Utils.Dispose(enumerator); 364 enumerator = next.GetEnumerator(); 365 } 366 } 367 }, 368 function () { Utils.Dispose(enumerator); }); 369 }); 370 }, 371 372 // Overload:function(func) 373 // Overload:function(func, resultSelector<element>) 374 // Overload:function(func, resultSelector<element, nestLevel>) 375 CascadeDepthFirst: function (func, resultSelector) 376 { 377 var source = this; 378 func = Utils.CreateLambda(func); 379 resultSelector = Utils.CreateLambda(resultSelector); 380 381 return new Enumerable(function () 382 { 383 var enumeratorStack = []; 384 var enumerator; 385 386 return new IEnumerator( 387 function () { enumerator = source.GetEnumerator(); }, 388 function () 389 { 390 while (true) 391 { 392 if (enumerator.MoveNext()) 393 { 394 var value = resultSelector(enumerator.Current(), enumeratorStack.length); 395 enumeratorStack.push(enumerator); 396 enumerator = Enumerable.From(func(enumerator.Current())).GetEnumerator(); 397 return this.Yield(value); 398 } 399 400 if (enumeratorStack.length <= 0) return false; 401 Utils.Dispose(enumerator); 402 enumerator = enumeratorStack.pop(); 403 } 404 }, 405 function () 406 { 407 try { Utils.Dispose(enumerator); } 408 finally { Enumerable.From(enumeratorStack).ForEach(function (s) { s.Dispose(); }) } 409 }); 410 }); 411 }, 412 413 Flatten: function () 414 { 415 var source = this; 416 417 return new Enumerable(function () 418 { 419 var enumerator; 420 var middleEnumerator = null; 421 422 return new IEnumerator( 423 function () { enumerator = source.GetEnumerator(); }, 424 function () 425 { 426 while (true) 427 { 428 if (middleEnumerator != null) 429 { 430 if (middleEnumerator.MoveNext()) 431 { 432 return this.Yield(middleEnumerator.Current()); 433 } 434 else 435 { 436 middleEnumerator = null; 437 } 438 } 439 440 if (enumerator.MoveNext()) 441 { 442 if (enumerator.Current() instanceof Array) 443 { 444 Utils.Dispose(middleEnumerator); 445 middleEnumerator = Enumerable.From(enumerator.Current()) 446 .SelectMany(Functions.Identity) 447 .Flatten() 448 .GetEnumerator(); 449 continue; 450 } 451 else 452 { 453 return this.Yield(enumerator.Current()); 454 } 455 } 456 457 return false; 458 } 459 }, 460 function () 461 { 462 try { Utils.Dispose(enumerator); } 463 finally { Utils.Dispose(middleEnumerator); } 464 }); 465 }); 466 }, 467 468 Pairwise: function (selector) 469 { 470 var source = this; 471 selector = Utils.CreateLambda(selector); 472 473 return new Enumerable(function () 474 { 475 var enumerator; 476 477 return new IEnumerator( 478 function () 479 { 480 enumerator = source.GetEnumerator(); 481 enumerator.MoveNext(); 482 }, 483 function () 484 { 485 var prev = enumerator.Current(); 486 return (enumerator.MoveNext()) 487 ? this.Yield(selector(prev, enumerator.Current())) 488 : false; 489 }, 490 function () { Utils.Dispose(enumerator); }); 491 }); 492 }, 493 494 // Overload:function(func) 495 // Overload:function(seed,func<value,element>) 496 // Overload:function(seed,func<value,element>,resultSelector) 497 Scan: function (seed, func, resultSelector) 498 { 499 if (resultSelector != null) return this.Scan(seed, func).Select(resultSelector); 500 501 var isUseSeed; 502 if (func == null) 503 { 504 func = Utils.CreateLambda(seed); // arguments[0] 505 isUseSeed = false; 506 } 507 else 508 { 509 func = Utils.CreateLambda(func); 510 isUseSeed = true; 511 } 512 var source = this; 513 514 return new Enumerable(function () 515 { 516 var enumerator; 517 var value; 518 var isFirst = true; 519 520 return new IEnumerator( 521 function () { enumerator = source.GetEnumerator(); }, 522 function () 523 { 524 if (isFirst) 525 { 526 isFirst = false; 527 if (!isUseSeed) 528 { 529 if (enumerator.MoveNext()) 530 { 531 return this.Yield(value = enumerator.Current()); 532 } 533 } 534 else 535 { 536 return this.Yield(value = seed); 537 } 538 } 539 540 return (enumerator.MoveNext()) 541 ? this.Yield(value = func(value, enumerator.Current())) 542 : false; 543 }, 544 function () { Utils.Dispose(enumerator); }); 545 }); 546 }, 547 548 // Overload:function(selector<element>) 549 // Overload:function(selector<element,index>) 550 Select: function (selector) 551 { 552 var source = this; 553 selector = Utils.CreateLambda(selector); 554 555 return new Enumerable(function () 556 { 557 var enumerator; 558 var index = 0; 559 560 return new IEnumerator( 561 function () { enumerator = source.GetEnumerator(); }, 562 function () 563 { 564 return (enumerator.MoveNext()) 565 ? this.Yield(selector(enumerator.Current(), index++)) 566 : false; 567 }, 568 function () { Utils.Dispose(enumerator); }) 569 }); 570 }, 571 572 // Overload:function(collectionSelector<element>) 573 // Overload:function(collectionSelector<element,index>) 574 // Overload:function(collectionSelector<element>,resultSelector) 575 // Overload:function(collectionSelector<element,index>,resultSelector) 576 SelectMany: function (collectionSelector, resultSelector) 577 { 578 var source = this; 579 collectionSelector = Utils.CreateLambda(collectionSelector); 580 if (resultSelector == null) resultSelector = function (a, b) { return b; } 581 resultSelector = Utils.CreateLambda(resultSelector); 582 583 return new Enumerable(function () 584 { 585 var enumerator; 586 var middleEnumerator = undefined; 587 var index = 0; 588 589 return new IEnumerator( 590 function () { enumerator = source.GetEnumerator(); }, 591 function () 592 { 593 if (middleEnumerator === undefined) 594 { 595 if (!enumerator.MoveNext()) return false; 596 } 597 do 598 { 599 if (middleEnumerator == null) 600 { 601 var middleSeq = collectionSelector(enumerator.Current(), index++); 602 middleEnumerator = Enumerable.From(middleSeq).GetEnumerator(); 603 } 604 if (middleEnumerator.MoveNext()) 605 { 606 return this.Yield(resultSelector(enumerator.Current(), middleEnumerator.Current())); 607 } 608 Utils.Dispose(middleEnumerator); 609 middleEnumerator = null; 610 } while (enumerator.MoveNext()) 611 return false; 612 }, 613 function () 614 { 615 try { Utils.Dispose(enumerator); } 616 finally { Utils.Dispose(middleEnumerator); } 617 }) 618 }); 619 }, 620 621 // Overload:function(predicate<element>) 622 // Overload:function(predicate<element,index>) 623 Where: function (predicate) 624 { 625 predicate = Utils.CreateLambda(predicate); 626 var source = this; 627 628 return new Enumerable(function () 629 { 630 var enumerator; 631 var index = 0; 632 633 return new IEnumerator( 634 function () { enumerator = source.GetEnumerator(
634); }, 635 function () 636 { 637 while (enumerator.MoveNext()) 638 { 639 if (predicate(enumerator.Current(), index++)) 640 { 641 return this.Yield(enumerator.Current()); 642 } 643 } 644 return false; 645 }, 646 function () { Utils.Dispose(enumerator); }) 647 }); 648 }, 649 650 OfType: function (type) 651 { 652 var typeName; 653 switch (type) 654 { 655 case Number: typeName = Types.Number; break; 656 case String: typeName = Types.String; break; 657 case Boolean: typeName = Types.Boolean; break; 658 case Function: typeName = Types.Function; break; 659 default: typeName = null; break; 660 } 661 return (typeName === null) 662 ? this.Where(function (x) { return x instanceof type }) 663 : this.Where(function (x) { return typeof x === typeName }); 664 }, 665 666 // Overload:function(second,selector<outer,inner>) 667 // Overload:function(second,selector<outer,inner,index>) 668 Zip: function (second, selector) 669 { 670 selector = Utils.CreateLambda(selector); 671 var source = this; 672 673 return new Enumerable(function () 674 { 675 var firstEnumerator; 676 var secondEnumerator; 677 var index = 0; 678 679 return new IEnumerator( 680 function () 681 { 682 firstEnumerator = source.GetEnumerator(); 683 secondEnumerator = Enumerable.From(second).GetEnumerator(); 684 }, 685 function () 686 { 687 if (firstEnumerator.MoveNext() && secondEnumerator.MoveNext()) 688 { 689 return this.Yield(selector(firstEnumerator.Current(), secondEnumerator.Current(), index++)); 690 } 691 return false; 692 }, 693 function () 694 { 695 try { Utils.Dispose(firstEnumerator); } 696 finally { Utils.Dispose(secondEnumerator); } 697 }) 698 }); 699 }, 700 701 /* Join Methods */ 702 703 // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector) 704 // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) 705 Join: function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) 706 { 707 outerKeySelector = Utils.CreateLambda(outerKeySelector); 708 innerKeySelector = Utils.CreateLambda(innerKeySelector); 709 resultSelector = Utils.CreateLambda(resultSelector); 710 compareSelector = Utils.CreateLambda(compareSelector); 711 var source = this; 712 713 return new Enumerable(function () 714 { 715 var outerEnumerator; 716 var lookup; 717 var innerElements = null; 718 var innerCount = 0; 719 720 return new IEnumerator( 721 function () 722 { 723 outerEnumerator = source.GetEnumerator(); 724 lookup = Enumerable.From(inner).ToLookup(innerKeySelector, Functions.Identity, compareSelector); 725 }, 726 function () 727 { 728 while (true) 729 { 730 if (innerElements != null) 731 { 732 var innerElement = innerElements[innerCount++]; 733 if (innerElement !== undefined) 734 { 735 return this.Yield(resultSelector(outerEnumerator.Current(), innerElement)); 736 } 737 738 innerElement = null; 739 innerCount = 0; 740 } 741 742 if (outerEnumerator.MoveNext()) 743 { 744 var key = outerKeySelector(outerEnumerator.Current()); 745 innerElements = lookup.Get(key).ToArray(); 746 } 747 else 748 { 749 return false; 750 } 751 } 752 }, 753 function () { Utils.Dispose(outerEnumerator); }) 754 }); 755 }, 756 757 // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector) 758 // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) 759 GroupJoin: function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) 760 { 761 outerKeySelector = Utils.CreateLambda(outerKeySelector); 762 innerKeySelector = Utils.CreateLambda(innerKeySelector); 763 resultSelector = Utils.CreateLambda(resultSelector); 764 compareSelector = Utils.CreateLambda(compareSelector); 765 var source = this; 766 767 return new Enumerable(function () 768 { 769 var enumerator = source.GetEnumerator(); 770 var lookup = null; 771 772 return new IEnumerator( 773 function () 774 { 775 enumerator = source.GetEnumerator(); 776 lookup = Enumerable.From(inner).ToLookup(innerKeySelector, Functions.Identity, compareSelector); 777 }, 778 function () 779 { 780 if (enumerator.MoveNext()) 781 { 782 var innerElement = lookup.Get(outerKeySelector(enumerator.Current())); 783 return this.Yield(resultSelector(enumerator.Current(), innerElement)); 784 } 785 return false; 786 }, 787 function () { Utils.Dispose(enumerator); }) 788 }); 789 }, 790 791 /* Set Methods */ 792 793 All: function (predicate) 794 { 795 predicate = Utils.CreateLambda(predicate); 796 797 var result = true; 798 this.ForEach(function (x) 799 { 800 if (!predicate(x)) 801 { 802 result = false; 803 return false; // break 804 } 805 }); 806 return result; 807 }, 808 809 // Overload:function() 810 // Overload:function(predicate) 811 Any: function (predicate) 812 { 813 predicate = Utils.CreateLambda(predicate); 814 815 var enumerator = this.GetEnumerator(); 816 try 817 { 818 if (arguments.length == 0) return enumerator.MoveNext(); // case:function() 819 820 while (enumerator.MoveNext()) // case:function(predicate) 821 { 822 if (predicate(enumerator.Current())) return true; 823 } 824 return false; 825 } 826 finally { Utils.Dispose(enumerator); } 827 }, 828 829 Concat: function (second) 830 { 831 var source = this; 832 833 return new Enumerable(function () 834 { 835 var firstEnumerator; 836 var secondEnumerator; 837 838 return new IEnumerator( 839 function () { firstEnumerator = source.GetEnumerator(); }, 840 function () 841 { 842 if (secondEnumerator == null) 843 { 844 if (firstEnumerator.MoveNext()) return this.Yield(firstEnumerator.Current()); 845 secondEnumerator = Enumerable.From(second).GetEnumerator(); 846 } 847 if (secondEnumerator.MoveNext()) return this.Yield(secondEnumerator.Current()); 848 return false; 849 }, 850 function () 851 { 852 try { Utils.Dispose(firstEnumerator); } 853 finally { Utils.Dispose(secondEnumerator); } 854 }) 855 }); 856 }, 857 858 Insert: function (index, second) 859 { 860 var source = this; 861 862 return new Enumerable(function () 863 { 864 var firstEnumerator; 865 var secondEnumerator; 866 var count = 0; 867 var isEnumerated = false; 868 869 return new IEnumerator( 870 function () 871 { 872 firstEnumerator = source.GetEnumerator(); 873 secondEnumerator = Enumerable.From(second).GetEnumerator(); 874 }, 875 function () 876 { 877 if (count == index && secondEnumerator.MoveNext()) 878 { 879 isEnumerated = true; 880 return this.Yield(secondEnumerator.Current()); 881 } 882 if (firstEnumerator.MoveNext()) 883 { 884 count++; 885 return this.Yield(firstEnumerator.Current()); 886 } 887 if (!isEnumerated && secondEnumerator.MoveNext()) 888 { 889 return this.Yield(secondEnumerator.Current()); 890 } 891 return false; 892 }, 893 function () 894 { 895 try { Utils.Dispose(firstEnumerator); } 896 finally { Utils.Dispose(secondEnumerator); } 897 }) 898 }); 899 }, 900 901 Alternate: function (value) 902 { 903 value = Enumerable.Return(value); 904 return this.SelectMany(function (elem) 905 { 906 return Enumerable.Return(elem).Concat(value); 907 }).TakeExceptLast(); 908 }, 909 910 // Overload:function(value) 911 // Overload:function(value, compareSelector) 912 Contains: function (value, compareSelector) 913 { 914 compareSelector = Utils.CreateLambda(compareSelector); 915 var enumerator = this.GetEnumerator(); 916 try 917 { 918 while (enumerator.MoveNext()) 919 { 920 if (compareSelector(enumerator.Current()) === value) return true; 921 } 922 return false; 923 } 924 finally { Utils.Dispose(enumerator) } 925 }, 926 927 DefaultIfEmpty: function (defaultValue) 928 { 929 var source = this; 930 931 return new Enumerable(function () 932 { 933 var enumerator; 934 var isFirst = true; 935 936 return new IEnumerator( 937 function () { enumerator = source.GetEnumerator(); }, 938 function () 939 { 940 if (enumerator.MoveNext()) 941 { 942 isFirst = false; 943 return this.Yield(enumerator.Current()); 944 } 945 else if (isFirst) 946 { 947 isFirst = false; 948 return this.Yield(defaultValue); 949 } 950 return false; 951 }, 952 function () { Utils.Dispose(enumerator); }) 953 }); 954 }, 955 956 // Overload:function() 957 // Overload:function(compareSelector) 958 Distinct: function (compareSelector) 959 { 960 return this.Except(Enumerable.Empty(), compareSelector); 961 }, 962 963 // Overload:function(second) 964 // Overload:function(second, compareSelector) 965 Except: function (second, compareSelector) 966 { 967 compareSelector = Utils.CreateLambda(compareSelector); 968 var source = this; 969 970 return new Enumerable(function () 971 { 972 var enumerator; 973 var keys; 974 975 return new IEnumerator( 976 function () 977 { 978 enumerator = source.GetEnumerator(); 979 keys = new Dictionary(compareSelector); 980 Enumerable.From(second).ForEach(function (key) { keys.Add(key); }); 981 }, 982 function () 983 { 984 while (enumerator.MoveNext()) 985 { 986 var current = enumerator.Current(); 987 if (!keys.Contains(current)) 988 { 989 keys.Add(current); 990 return this.Yield(current); 991 } 992 } 993 return false; 994 }, 995 function () { Utils.Dispose(enumerator); }) 996 }); 997 }, 998 999 // Overload:function(second) 1000 // Overload:function(second, compareSelector) 1001 Intersect: function (second, compareSelector) 1002 { 1003 compareSelector = Utils.CreateLambda(compareSelector); 1004 var source = this; 1005 1006 return new Enumerable(function () 1007 { 1008 var enumerator; 1009 var keys; 1010 var outs; 1011 1012 return new IEnumerator( 1013 function () 1014 { 1015 enumerator = source.GetEnumerator(); 1016 1017 keys = new Dictionary(compareSelector); 1018 Enumerable.From(second).ForEach(function (key) { keys.Add(key); }); 1019 outs = new Dictionary(compareSelector); 1020 }, 1021 function () 1022 { 1023 while (enumerator.MoveNext()) 1024 { 1025 var current = enumerator.Current(); 1026 if (!outs.Contains(current) && keys.Contains(current)) 1027 { 1028 outs.Add(current); 1029 return this.Yield(current); 1030 } 1031 } 1032 return false; 1033 }, 1034 function () { Utils.Dispose(enumerator); }) 1035 }); 1036 }, 1037 1038 // Overload:function(second) 1039 // Overload:function(second, compareSelector) 1040 SequenceEqual: function (second, compareSelector) 1041 { 1042 compareSelector = Utils.CreateLambda(compareSelector); 1043 1044 var firstEnumerator = this.GetEnumerator(); 1045 try 1046 { 1047 var secondEnumerator = Enumerable.From(second).GetEnumerator(); 1048 try 1049 { 1050 while (firstEnumerator.MoveNext()) 1051 { 1052 if (!secondEnumerator.MoveNext() 1053 || compareSelector(firstEnumerator.Current()) !== compareSelector(secondEnumerator.Current())) 1054 { 1055 return false; 1056 } 1057 } 1058 1059 if (secondEnumerator.MoveNext()) return false; 1060 return true; 1061 } 1062 finally { Utils.Dispose(secondEnumerator); } 1063 } 1064 finally { Utils.Dispose(firstEnumerator); } 1065 }, 1066 1067 Union: function (se
1067cond, compareSelector) 1068 { 1069 compareSelector = Utils.CreateLambda(compareSelector); 1070 var source = this; 1071 1072 return new Enumerable(function () 1073 { 1074 var firstEnumerator; 1075 var secondEnumerator; 1076 var keys; 1077 1078 return new IEnumerator( 1079 function () 1080 { 1081 firstEnumerator = source.GetEnumerator(); 1082 keys = new Dictionary(compareSelector); 1083 }, 1084 function () 1085 { 1086 var current; 1087 if (secondEnumerator === undefined) 1088 { 1089 while (firstEnumerator.MoveNext()) 1090 { 1091 current = firstEnumerator.Current(); 1092 if (!keys.Contains(current)) 1093 { 1094 keys.Add(current); 1095 return this.Yield(current); 1096 } 1097 } 1098 secondEnumerator = Enumerable.From(second).GetEnumerator(); 1099 } 1100 while (secondEnumerator.MoveNext()) 1101 { 1102 current = secondEnumerator.Current(); 1103 if (!keys.Contains(current)) 1104 { 1105 keys.Add(current); 1106 return this.Yield(current); 1107 } 1108 } 1109 return false; 1110 }, 1111 function () 1112 { 1113 try { Utils.Dispose(firstEnumerator); } 1114 finally { Utils.Dispose(secondEnumerator); } 1115 }) 1116 }); 1117 }, 1118 1119 /* Ordering Methods */ 1120 1121 OrderBy: function (keySelector) 1122 { 1123 return new OrderedEnumerable(this, keySelector, false); 1124 }, 1125 1126 OrderByDescending: function (keySelector) 1127 { 1128 return new OrderedEnumerable(this, keySelector, true); 1129 }, 1130 1131 Reverse: function () 1132 { 1133 var source = this; 1134 1135 return new Enumerable(function () 1136 { 1137 var buffer; 1138 var index; 1139 1140 return new IEnumerator( 1141 function () 1142 { 1143 buffer = source.ToArray(); 1144 index = buffer.length; 1145 }, 1146 function () 1147 { 1148 return (index > 0) 1149 ? this.Yield(buffer[--index]) 1150 : false; 1151 }, 1152 Functions.Blank) 1153 }); 1154 }, 1155 1156 Shuffle: function () 1157 { 1158 var source = this; 1159 1160 return new Enumerable(function () 1161 { 1162 var buffer; 1163 1164 return new IEnumerator( 1165 function () { buffer = source.ToArray(); }, 1166 function () 1167 { 1168 if (buffer.length > 0) 1169 { 1170 var i = Math.floor(Math.random() * buffer.length); 1171 return this.Yield(buffer.splice(i, 1)[0]); 1172 } 1173 return false; 1174 }, 1175 Functions.Blank) 1176 }); 1177 }, 1178 1179 /* Grouping Methods */ 1180 1181 // Overload:function(keySelector) 1182 // Overload:function(keySelector,elementSelector) 1183 // Overload:function(keySelector,elementSelector,resultSelector) 1184 // Overload:function(keySelector,elementSelector,resultSelector,compareSelector) 1185 GroupBy: function (keySelector, elementSelector, resultSelector, compareSelector) 1186 { 1187 var source = this; 1188 keySelector = Utils.CreateLambda(keySelector); 1189 elementSelector = Utils.CreateLambda(elementSelector); 1190 if (resultSelector != null) resultSelector = Utils.CreateLambda(resultSelector); 1191 compareSelector = Utils.CreateLambda(compareSelector); 1192 1193 return new Enumerable(function () 1194 { 1195 var enumerator; 1196 1197 return new IEnumerator( 1198 function () 1199 { 1200 enumerator = source.ToLookup(keySelector, elementSelector, compareSelector) 1201 .ToEnumerable() 1202 .GetEnumerator(); 1203 }, 1204 function () 1205 { 1206 while (enumerator.MoveNext()) 1207 {
1208 return (resultSelector == null) 1209 ? this.Yield(enumerator.Current()) 1210 : this.Yield(resultSelector(enumerator.Current().Key(), enumerator.Current())); 1211 } 1212 return false; 1213 }, 1214 function () { Utils.Dispose(enumerator); }) 1215 }); 1216 }, 1217 1218 // Overload:function(keySelector) 1219 // Overload:function(keySelector,elementSelector) 1220 // Overload:function(keySelector,elementSelector,resultSelector) 1221 // Overload:function(keySelector,elementSelector,resultSelector,compareSelector) 1222 PartitionBy: function (keySelector, elementSelector, resultSelector, compareSelector) 1223 { 1224 1225 var source = this; 1226 keySelector = Utils.CreateLambda(keySelector); 1227 elementSelector = Utils.CreateLambda(elementSelector); 1228 compareSelector = Utils.CreateLambda(compareSelector); 1229 var hasResultSelector; 1230 if (resultSelector == null) 1231 { 1232 hasResultSelector = false; 1233 resultSelector = function (key, group) { return new Grouping(key, group) } 1234 } 1235 else 1236 { 1237 hasResultSelector = true; 1238 resultSelector = Utils.CreateLambda(resultSelector); 1239 } 1240 1241 return new Enumerable(function () 1242 { 1243 var enumerator; 1244 var key; 1245 var compareKey; 1246 var group = []; 1247 1248 return new IEnumerator( 1249 function () 1250 { 1251 enumerator = source.GetEnumerator(); 1252 if (enumerator.MoveNext()) 1253 { 1254 key = keySelector(enumerator.Current()); 1255 compareKey = compareSelector(key); 1256 group.push(elementSelector(enumerator.Current())); 1257 } 1258 }, 1259 function () 1260 { 1261 var hasNext; 1262 while ((hasNext = enumerator.MoveNext()) == true) 1263 { 1264 if (compareKey === compareSelector(keySelector(enumerator.Current()))) 1265 { 1266 group.push(elementSelector(enumerator.Current())); 1267 } 1268 else break; 1269 } 1270 1271 if (group.length > 0) 1272 { 1273 var result = (hasResultSelector) 1274 ? resultSelector(key, Enumerable.From(group)) 1275 : resultSelector(key, group); 1276 if (hasNext) 1277 { 1278 key = keySelector(enumerator.Current()); 1279 compareKey = compareSelector(key); 1280 group = [elementSelector(enumerator.Current())]; 1281 } 1282 else group = []; 1283 1284 return this.Yield(result); 1285 } 1286 1287 return false; 1288 }, 1289 function () { Utils.Dispose(enumerator); }) 1290 }); 1291 }, 1292 1293 BufferWithCount: function (count) 1294 { 1295 var source = this; 1296 1297 return new Enumerable(function () 1298 { 1299 var enumerator; 1300 1301 return new IEnumerator( 1302 function () { enumerator = source.GetEnumerator(); }, 1303 function () 1304 { 1305 var array = []; 1306 var index = 0; 1307 while (enumerator.MoveNext()) 1308 { 1309 array.push(enumerator.Current()); 1310 if (++index >= count) return this.Yield(array); 1311 } 1312 if (array.length > 0) return this.Yield(array); 1313 return false; 1314 }, 1315 function () { Utils.Dispose(enumerator); }) 1316 }); 1317 }, 1318 1319 /* Aggregate Methods */ 1320 1321 // Overload:function(func) 1322 // Overload:function(seed,func) 1323 // Overload:function(seed,func,resultSelector) 1324 Aggregate: function (seed, func, resultSelector) 1325 { 1326 return this.Scan(seed, func, resultSelector).Last(); 1327 }, 1328 1329 // Overload:function() 1330 // Overload:function(selector) 1331 Average: function (selector) 1332 { 1333 selector = Utils.CreateLambda(selector); 1334 1335 var sum = 0; 1336 var count = 0; 1337 this.ForEach(function (x) 1338 { 1339 sum += selector(x); 1340 ++count; 1341 }); 1342 1343 return sum / count; 1344 }, 1345 1346 // Overload:function() 1347 // Overload:function(predicate) 1348 Count: function (predicate) 1349 { 1350 predicate = (predicate == null) ? Functions.True : Utils.CreateLambda(predicate); 1351 1352 var count = 0; 1353 this.ForEach(function (x, i) 1354 { 1355 if (predicate(x, i)) ++count; 1356 }); 1357 return count; 1358 }, 1359 1360 // Overload:function() 1361 // Overload:function(selector) 1362 Max: function (selector) 1363 { 1364 if (selector == null) selector = Functions.Identity; 1365 return this.Select(selector).Aggregate(function (a, b) { return (a > b) ? a : b; }); 1366 }, 1367 1368 // Overload:function() 1369 // Overload:function(selector) 1370 Min: function (selector) 1371 { 1372 if (selector == null) selector = Functions.Identity; 1373 return this.Select(selector).Aggregate(function (a, b) { return (a < b) ? a : b; }); 1374 }, 1375 1376 MaxBy: function (keySelector) 1377 { 1378 keySelector = Utils.CreateLambda(keySelector); 1379 return this.Aggregate(function (a, b) { return (keySelector(a) > keySelector(b)) ? a : b }); 1380 }, 1381 1382 MinBy: function (keySelector) 1383 { 1384 keySelector = Utils.CreateLambda(keySelector); 1385 return this.Aggregate(function (a, b) { return (keySelector(a) < keySelector(b)) ? a : b }); 1386 }, 1387 1388 // Overload:function() 1389 // Overload:function(selector) 1390 Sum: function (selector) 1391 { 1392 if (selector == null) selector = Functions.Identity; 1393 return this.Select(selector).Aggregate(0, function (a, b) { return a + b; }); 1394 }, 1395 1396 /* Paging Methods */ 1397 1398 ElementAt: function (index) 1399 { 1400 var value; 1401 var found = false; 1402 this.ForEach(function (x, i) 1403 { 1404 if (i == index) 1405 { 1406 value = x; 1407 found = true; 1408 return false; 1409 } 1410 }); 1411 1412 if (!found) throw new Error("index is less than 0 or greater than or equal to the number of elements in source."); 1413 return value; 1414 }, 1415 1416 ElementAtOrDefault: function (index, defaultValue) 1417 { 1418 var value; 1419 var found = false; 1420 this.ForEach(function (x, i) 1421 { 1422 if (i == index) 1423 { 1424 value = x; 1425 found = true; 1426 return false; 1427 } 1428 }); 1429 1430 return (!found) ? defaultValue : value; 1431 }, 1432 1433 // Overload:function() 1434 // Overload:function(predicate) 1435 First: function (predicate) 1436 { 1437 if (predicate != null) return this.Where(predicate).First(); 1438 1439 var value; 1440 var found = false; 1441 this.ForEach(function (x) 1442 { 1443 value = x; 1444 found = true; 1445 return false; 1446 }); 1447 1448 if (!found) throw new Error("First:No element satisfies the condition."); 1449 return value; 1450 }, 1451 1452 // Overload:function(defaultValue) 1453 // Overload:function(defaultValue,predicate) 1454 FirstOrDefault: function (defaultValue, predicate) 1455 { 1456 if (predicate != null) return this.Where(predicate).FirstOrDefault(defaultValue); 1457 1458 var value; 1459 var found = false; 1460 this.ForEach(function (x) 1461 { 1462 value = x; 1463 found = true; 1464 return false; 1465 }); 1466 return (!found) ? defaultValue : value; 1467 }, 1468 1469 // Overload:function() 1470 // Overload:function(predicate) 1471 Last: function (predicate) 1472 { 1473 if (predicate != null) return this.Where(predicate).Last(); 1474 1475 var value; 1476 var found = false; 1477 this.ForEach(function (x) 1478 { 1479 found = true; 1480 value = x; 1481 }); 1482 1483 if (!found) throw new Error("Last:No element satisfies the condition."); 1484 return value; 1485 }, 1486 1487 // Overload:function(defaultValue) 1488 // Overload:function(defaultValue,predicate) 1489 LastOrDefault: function (defaultValue, predicate) 1490 { 1491 if (predicate != null) return this.Where(predicate).LastOrDefault(defaultValue); 1492 1493 var value; 1494 var found = false; 1495 this.ForEach(function (x) 1496 { 1497 found = true; 1498 value = x; 1499 }); 1500 return (!found) ? defaultValue : value; 1501 }, 1502 1503 // Overload:function() 1504 // Overload:function(predicate) 1505 Single: function (predicate) 1506 { 1507 if (predicate != null) return this.Where(predicate).Single(); 1508 1509 var value; 1510 var found = false; 1511 this.ForEach(function (x) 1512 { 1513 if (!found) 1514 { 1515 found = true; 1516 value = x; 1517 } 1518 else throw new Error("Single:sequence contains more than one element."); 1519 }); 1520 1521 if (!found) throw new Error("Single:No element satisfies the condition."); 1522 return value; 1523 }, 1524 1525 // Overload:function(defaultValue) 1526 // Overload:function(defaultValue,predicate) 1527 SingleOrDefault: function (defaultValue, predicate) 1528 { 1529 if (predicate != null) return this.Where(predicate).SingleOrDefault(defaultValue); 1530 1531 var value; 1532 var found = false; 1533 this.ForEach(function (x) 1534 { 1535 if (!found) 1536 { 1537 found = true; 1538 value = x; 1539 } 1540 else throw new Error("Single:sequence contains more than one element."); 1541 }); 1542 1543 return (!found) ? defaultValue : value; 1544 }, 1545 1546 Skip: function (count) 1547 { 1548 var source = this; 1549 1550 return new Enumerable(function () 1551 { 1552 var enumerator; 1553 var index = 0; 1554 1555 return new IEnumerator( 1556 function () 1557 { 1558 enumerator = source.GetEnumerator(); 1559 while (index++ < count && enumerator.MoveNext()) { }; 1560 }, 1561 function () 1562 { 1563 return (enumerator.MoveNext()) 1564 ? this.Yield(enumerator.Current()) 1565 : false; 1566 }, 1567 function () { Utils.Dispose(enumerator); }) 1568 }); 1569 }, 1570 1571 // Overload:function(predicate<element>) 1572 // Overload:function(predicate<element,index>) 1573 SkipWhile: function (predicate) 1574 { 1575 predicate = Utils.CreateLambda(predicate); 1576 var source = this; 1577 1578 return new Enumerable(function () 1579 { 1580 var enumerator; 1581 var index = 0; 1582 var isSkipEnd = false; 1583 1584 return new IEnumerator( 1585 function () { enumerator = source.GetEnumerator(); }, 1586 function () 1587 { 1588 while (!isSkipEnd) 1589 { 1590 if (enumerator.MoveNext()) 1591 { 1592 if (!predicate(enumerator.Current(), index++)) 1593 { 1594 isSkipEnd = true; 1595 return this.Yield(enumerator.Current()); 1596 } 1597 continue; 1598 } 1599 else return false; 1600 } 1601 1602 return (enumerator.MoveNext()) 1603 ? this.Yield(enumerator.Current()) 1604 : false; 1605 1606 }, 1607 function () { Utils.Dispose(enumerator); }); 1608 }); 1609 }, 1610 1611 Take: function (count) 1612 { 1613 var source = this; 1614 1615 return new Enumerable(function () 1616 { 1617 var enumerator; 1618 var index = 0; 1619 1620 return new IEnumerator( 1621 function () { enumerator = source.GetEnumerator(); }, 1622 function () 1623 { 1624 return (index++ < count && enumerator.MoveNext()) 1625 ? this.Yield(enumerator.Current()) 1626 : false; 1627 }, 1628 function () { Utils.Dispose(enumerator); } 1629 ) 1630 }); 1631 }, 1632 1633 // Overload:function(predicate<element>) 1634 // Overload:function(predicate<element,index>) 1635 TakeWhile: function (predicate) 1636 { 1637 predicate = Utils.CreateLambda(predicate); 1638 var source = this; 1639 1640 return new Enumerable(function () 1641 { 1642 var enumerator; 1643 var index = 0; 1644 1645 return new IEnumerator( 1646 function () { enumerator = source.GetEnumerator(); }, 1647 function () 1648 { 1649 return (enumerator.MoveNext() && predicate(enumerator.Current(), index++)) 1650 ? this.Yield(enumerator.Current()) 1651 : false; 1652 }, 1653 function () { Utils.Dispose(enumerator); }); 1654 }); 1655 }, 1656 1657 // Overload:function() 1658 // Overload:function(count) 1659 TakeExceptLast: function (count) 1660 { 1661 if (count == null) count = 1; 1662 var source = this; 1663 1664 return new Enumerable(function () 1665 { 1666 if (count <= 0) return source.GetEnumerator(); // do nothing 1667 1668 var enumerator; 1669 var q = []; 1670 1671 return new IEnumerator( 1672 function () { enumerator = source.GetEnumerator(); }, 1673 function () 1674 { 1675 while (enumerator.MoveNext()) 1676 { 1677 if (q.length == count) 1678 { 1679 q.push(enumerator.Current()); 1680 return this.Yield(q.shift()); 1681 } 1682 q.push(enumerator.Current()); 1683 } 1684 return false; 1685 }, 1686 function () { Utils.Dispose(enumerator); }); 1687 }); 1688 }, 1689 1690 TakeFromLast: function (count) 1691
1691 { 1692 if (count <= 0 || count == null) return Enumerable.Empty(); 1693 var source = this; 1694 1695 return new Enumerable(function () 1696 { 1697 var sourceEnumerator; 1698 var enumerator; 1699 var q = []; 1700 1701 return new IEnumerator( 1702 function () { sourceEnumerator = source.GetEnumerator(); }, 1703 function () 1704 { 1705 while (sourceEnumerator.MoveNext()) 1706 { 1707 if (q.length == count) q.shift() 1708 q.push(sourceEnumerator.Current()); 1709 } 1710 if (enumerator == null) 1711 { 1712 enumerator = Enumerable.From(q).GetEnumerator(); 1713 } 1714 return (enumerator.MoveNext()) 1715 ? this.Yield(enumerator.Current()) 1716 : false; 1717 }, 1718 function () { Utils.Dispose(enumerator); }); 1719 }); 1720 }, 1721 1722 IndexOf: function (item) 1723 { 1724 var found = null; 1725 this.ForEach(function (x, i) 1726 { 1727 if (x === item) 1728 { 1729 found = i; 1730 return true; 1731 } 1732 }); 1733 1734 return (found !== null) ? found : -1; 1735 }, 1736 1737 LastIndexOf: function (item) 1738 { 1739 var result = -1; 1740 this.ForEach(function (x, i) 1741 { 1742 if (x === item) result = i; 1743 }); 1744 1745 return result; 1746 }, 1747 1748 /* Convert Methods */ 1749 1750 ToArray: function () 1751 { 1752 var array = []; 1753 this.ForEach(function (x) { array.push(x) }); 1754 return array; 1755 }, 1756 1757 // Overload:function(keySelector) 1758 // Overload:function(keySelector, elementSelector) 1759 // Overload:function(keySelector, elementSelector, compareSelector) 1760 ToLookup: function (keySelector, elementSelector, compareSelector) 1761 { 1762 keySelector = Utils.CreateLambda(keySelector); 1763 elementSelector = Utils.CreateLambda(elementSelector); 1764 compareSelector = Utils.CreateLambda(compareSelector); 1765 1766 var dict = new Dictionary(compareSelector); 1767 this.ForEach(function (x) 1768 { 1769 var key = keySelector(x); 1770 var element = elementSelector(x); 1771 1772 var array = dict.Get(key); 1773 if (array !== undefined) array.push(element); 1774 else dict.Add(key, [element]); 1775 }); 1776 return new Lookup(dict); 1777 }, 1778 1779 ToObject: function (keySelector, elementSelector) 1780 { 1781 keySelector = Utils.CreateLambda(keySelector); 1782 elementSelector = Utils.CreateLambda(elementSelector); 1783 1784 var obj = {}; 1785 this.ForEach(function (x) 1786 { 1787 obj[keySelector(x)] = elementSelector(x); 1788 }); 1789 return obj; 1790 }, 1791 1792 // Overload:function(keySelector, elementSelector) 1793 // Overload:function(keySelector, elementSelector, compareSelector) 1794 ToDictionary: function (keySelector, elementSelector, compareSelector) 1795 { 1796 keySelector = Utils.CreateLambda(keySelector); 1797 elementSelector = Utils.CreateLambda(elementSelector); 1798 compareSelector = Utils.CreateLambda(compareSelector); 1799 1800 var dict = new Dictionary(compareSelector); 1801 this.ForEach(function (x) 1802 { 1803 dict.Add(keySelector(x), elementSelector(x)); 1804 }); 1805 return dict; 1806 }, 1807 1808 // Overload:function() 1809 // Overload:function(replacer) 1810 // Overload:function(replacer, space) 1811 ToJSON: function (replacer, space) 1812 { 1813 return JSON.stringify(this.ToArray(), replacer, space); 1814 }, 1815 1816 // Overload:function() 1817 // Overload:function(separator) 1818 // Overload:function(separator,selector) 1819 ToString: function (separator, selector) 1820 { 1821 if (separator == null) separator = ""; 1822 if (selector == null) selector = Functions.Identity; 1823 1824 return this.Select(selector).ToArray().join(separator); 1825 }, 1826 1827 1828 /* Action Methods */ 1829 1830 // Overload:function(action<element>) 1831 // Overload:function(action<element,index>) 1832 Do: function (action) 1833 { 1834 var source = this; 1835 action = Utils.CreateLambda(action); 1836 1837 return new Enumerable(function () 1838 { 1839 var enumerator; 1840 var index = 0; 1841 1842 return new IEnumerator( 1843 function () { enumerator = source.GetEnumerator(); }, 1844 function () 1845 { 1846 if (enumerator.MoveNext()) 1847 { 1848 action(enumerator.Current(), index++); 1849 return this.Yield(enumerator.Current()); 1850 } 1851 return false; 1852 }, 1853 function () { Utils.Dispose(enumerator); }); 1854 }); 1855 }, 1856 1857 // Overload:function(action<element>) 1858 // Overload:function(action<element,index>) 1859 // Overload:function(func<element,bool>) 1860 // Overload:function(func<element,index,bool>) 1861 ForEach: function (action) 1862 { 1863 action = Utils.CreateLambda(action); 1864 1865 var index = 0; 1866 var enumerator = this.GetEnumerator(); 1867 try 1868 { 1869 while (enumerator.MoveNext()) 1870 { 1871 if (action(enumerator.Current(), index++) === false) break; 1872 } 1873 } 1874 finally { Utils.Dispose(enumerator); } 1875 }, 1876 1877 // Overload:function() 1878 // Overload:function(separator) 1879 // Overload:function(separator,selector) 1880 Write: function (separator, selector) 1881 { 1882 if (separator == null) separator = ""; 1883 selector = Utils.CreateLambda(selector); 1884 1885 var isFirst = true; 1886 this.ForEach(function (item) 1887 { 1888 if (isFirst) isFirst = false; 1889 else document.write(separator); 1890 document.write(selector(item)); 1891 }); 1892 }, 1893 1894 // Overload:function() 1895 // Overload:function(selector) 1896 WriteLine: function (selector) 1897 { 1898 selector = Utils.CreateLambda(selector); 1899 1900 this.ForEach(function (item) 1901 { 1902 document.write(selector(item)); 1903 document.write("<br />"); 1904 }); 1905 }, 1906 1907 Force: function () 1908 { 1909 var enumerator = this.GetEnumerator(); 1910 1911 try { while (enumerator.MoveNext()) { } } 1912 finally { Utils.Dispose(enumerator); } 1913 }, 1914 1915 /* Functional Methods */ 1916 1917 Let: function (func) 1918 { 1919 func = Utils.CreateLambda(func); 1920 var source = this; 1921 1922 return new Enumerable(function () 1923 { 1924 var enumerator; 1925 1926 return new IEnumerator( 1927 function () 1928 { 1929 enumerator = Enumerable.From(func(source)).GetEnumerator(); 1930 }, 1931 function () 1932 { 1933 return (enumerator.MoveNext()) 1934 ? this.Yield(enumerator.Current()) 1935 : false; 1936 }, 1937 function () { Utils.Dispose(enumerator); }) 1938 }); 1939 }, 1940 1941 Share: function () 1942 { 1943 var source = this; 1944 var sharedEnumerator; 1945 1946 return new Enumerable(function () 1947 { 1948 return new IEnumerator( 1949 function () 1950 { 1951 if (sharedEnumerator == null) 1952 { 1953 sharedEnumerator = source.GetEnumerator(); 1954 } 1955 }, 1956 function () 1957 { 1958 return (sharedEnumerator.MoveNext()) 1959 ? this.Yield(sharedEnumerator.Current()) 1960 : false; 1961 }, 1962 Functions.Blank 1963 ) 1964 }); 1965 }, 1966 1967 MemoizeAll: function () 1968 { 1969 var source = this; 1970 var cache; 1971 var enumerator; 1972 1973 return new Enumerable(function () 1974 { 1975 var index = -1; 1976 1977 return new IEnumerator( 1978 function () 1979 { 1980 if (enumerator == null) 1981 { 1982 enumerator = source.GetEnumerator(); 1983 cache = []; 1984 } 1985 }, 1986 function () 1987 { 1988 index++; 1989 if (cache.length <= index) 1990 { 1991 return (enumerator.MoveNext()) 1992 ? this.Yield(cache[index] = enumerator.Current()) 1993 : false; 1994 } 1995 1996 return this.Yield(cache[index]); 1997 }, 1998 Functions.Blank 1999 ) 2000 }); 2001 }, 2002 2003 /* Error Handling Methods */ 2004 2005 Catch: function (handler) 2006 { 2007 handler = Utils.CreateLambda(handler); 2008 var source = this; 2009 2010 return new Enumerable(function () 2011 { 2012 var enumerator; 2013 2014 return new IEnumerator( 2015 function () { enumerator = source.GetEnumerator(); }, 2016 function () 2017 { 2018 try 2019 { 2020 return (enumerator.MoveNext()) 2021 ? this.Yield(enumerator.Current()) 2022 : false; 2023 } 2024 catch (e) 2025 { 2026 handler(e); 2027 return false; 2028 } 2029 }, 2030 function () { Utils.Dispose(enumerator); }); 2031 }); 2032 }, 2033 2034 Finally: function (finallyAction) 2035 { 2036 finallyAction = Utils.CreateLambda(finallyAction); 2037 var source = this; 2038 2039 return new Enumerable(function () 2040 { 2041 var enumerator; 2042 2043 return new IEnumerator( 2044 function () { enumerator = source.GetEnumerator(); }, 2045 function () 2046 { 2047 return (enumerator.MoveNext()) 2048 ? this.Yield(enumerator.Current()) 2049 : false; 2050 }, 2051 function () 2052 { 2053 try { Utils.Dispose(enumerator); } 2054 finally { finallyAction(); } 2055 }); 2056 }); 2057 }, 2058 2059 /* For Debug Methods */ 2060 2061 // Overload:function() 2062 // Overload:function(message) 2063 // Overload:function(message,selector) 2064 Trace: function (message, selector) 2065 { 2066 if (message == null) message = "Trace"; 2067 selector = Utils.CreateLambda(selector); 2068 2069 return this.Do(function (item) 2070 { 2071 console.log(message, ":", selector(item)); 2072 }); 2073 } 2074 } 2075 2076 // private 2077 2078 // static functions 2079 var Functions = 2080 { 2081 Identity: function (x) { return x; }, 2082 True: function () { return true; }, 2083 Blank: function () { } 2084 } 2085 2086 // static const 2087 var Types = 2088 { 2089 Boolean: typeof true, 2090 Number: typeof 0, 2091 String: typeof "", 2092 Object: typeof {}, 2093 Undefined: typeof undefined, 2094 Function: typeof function () { } 2095 } 2096 2097 // static utility methods 2098 var Utils = 2099 { 2100 // Create anonymous function from lambda expression string 2101 CreateLambda: function (expression) 2102 { 2103 if (expression == null) return Functions.Identity; 2104 if (typeof expression == Types.String) 2105 { 2106 if (expression == "") 2107 { 2108 return Functions.Identity; 2109 } 2110 else if (expression.indexOf("=>") == -1) 2111 { 2112 return new Function("$,$$,$$$,$$$$", "return " + expression); 2113 } 2114 else 2115 { 2116 var expr = expression.match(/^[(\s]*([^()]*?)[)\s]*=>(.*)/); 2117 return new Function(expr[1], "return " + expr[2]); 2118 } 2119 } 2120 return expression; 2121 }, 2122 2123 IsIEnumerable: function (obj) 2124 { 2125 if (typeof Enumerator != Types.Undefined) 2126 { 2127 try 2128 { 2129 new Enumerator(obj); 2130 return true; 2131 } 2132 catch (e) { } 2133 } 2134 return false; 2135 }, 2136 2137 Compare: function (a, b) 2138 { 2139 return (a === b) ? 0 2140 : (a > b) ? 1 2141 : -1; 2142 }, 2143 2144 Dispose: function (obj) 2145 { 2146 if (obj != null) obj.Dispose(); 2147 } 2148 } 2149 2150 // IEnumerator State 2151 var State = { Before: 0, Running: 1, After: 2 } 2152 2153 // name "Enumerator" is conflict JScript's "Enumerator" 2154 var IEnumerator = function (initialize, tryGetNext, dispose) 2155 { 2156 var yielder = new Yielder(); 2157 var state = State.Before; 2158 2159 this.Current = yielder.Current; 2160 this.MoveNext = function () 2161 { 2162 try 2163 { 2164 switch (state) 2165 { 2166 case State.Before: 2167 state = State.Running; 2168 initialize(); // fall through 2169 case State.Running: 2170 if (tryGetNext.apply(yielder)) 2171 { 2172 return true; 2173 } 2174 else 2175 { 2176 this.Dispose(); 2177 return false; 2178 } 2179 case State.After: 2180 return false; 2181 } 2182 } 2183 catch (e) 2184 { 2185 this.Dispose(); 2186 throw e; 2187 } 2188 } 2189 this.Dispose = function () 2190 { 2191 if (state != State.Running) return; 2192 2193 try { dispose(); } 2194 finally { state = State.After; } 2195 } 2196 } 2197 2198 // for tryGetNext 2199 var Yielder = function () 2200 { 2201 var current = null; 2202 this.Current = function () { return current; } 2203 this.Yield = function (value) 2204 { 2205 current = value; 2206 return true; 2207 } 2208 } 2209 2210 // for OrderBy/ThenBy 2211 2212 var OrderedEnumerable = function (source, keySelector, descending, parent) 2213 { 2214 this.source = source; 2215 this.keySelector = Utils.CreateLambda(keySelector);
2216 this.descending = descending; 2217 this.parent = parent; 2218 } 2219 OrderedEnumerable.prototype = new Enumerable(); 2220 2221 OrderedEnumerable.prototype.CreateOrderedEnumerable = function (keySelector, descending) 2222 { 2223 return new OrderedEnumerable(this.source, keySelector, descending, this); 2224 } 2225 2226 OrderedEnumerable.prototype.ThenBy = function (keySelector) 2227 { 2228 return this.CreateOrderedEnumerable(keySelector, false); 2229 } 2230 2231 OrderedEnumerable.prototype.ThenByDescending = function (keySelector) 2232 { 2233 return this.CreateOrderedEnumerable(keySelector, true); 2234 } 2235 2236 OrderedEnumerable.prototype.GetEnumerator = function () 2237 { 2238 var self = this; 2239 var buffer; 2240 var indexes; 2241 var index = 0; 2242 2243 return new IEnumerator( 2244 function () 2245 { 2246 buffer = []; 2247 indexes = []; 2248 self.source.ForEach(function (item, index) 2249 { 2250 buffer.push(item); 2251 indexes.push(index); 2252 }); 2253 var sortContext = SortContext.Create(self, null); 2254 sortContext.GenerateKeys(buffer); 2255 2256 indexes.sort(function (a, b) { return sortContext.Compare(a, b); }); 2257 }, 2258 function () 2259 { 2260 return (index < indexes.length) 2261 ? this.Yield(buffer[indexes[index++]]) 2262 : false; 2263 }, 2264 Functions.Blank 2265 ) 2266 } 2267 2268 var SortContext = function (keySelector, descending, child) 2269 { 2270 this.keySelector = keySelector; 2271 this.descending = descending; 2272 this.child = child; 2273 this.keys = null; 2274 } 2275 2276 SortContext.Create = function (orderedEnumerable, currentContext) 2277 { 2278 var context = new SortContext(orderedEnumerable.keySelector, orderedEnumerable.descending, currentContext); 2279 if (orderedEnumerable.parent != null) return SortContext.Create(orderedEnumerable.parent, context); 2280 return context; 2281 } 2282 2283 SortContext.prototype.GenerateKeys = function (source) 2284 { 2285 var len = source.length; 2286 var keySelector = this.keySelector; 2287 var keys = new Array(len); 2288 for (var i = 0; i < len; i++) keys[i] = keySelector(source[i]); 2289 this.keys = keys; 2290 2291 if (this.child != null) this.child.GenerateKeys(source); 2292 } 2293 2294 SortContext.prototype.Compare = function (index1, index2) 2295 { 2296 var comparison = Utils.Compare(this.keys[index1], this.keys[index2]); 2297 2298 if (comparison == 0) 2299 { 2300 if (this.child != null) return this.child.Compare(index1, index2) 2301 comparison = Utils.Compare(index1, index2); 2302 } 2303 2304 return (this.descending) ? -comparison : comparison; 2305 } 2306 2307 // optimize array or arraylike object 2308 2309 var ArrayEnumerable = function (source) 2310 { 2311 this.source = source; 2312 } 2313 ArrayEnumerable.prototype = new Enumerable(); 2314 2315 ArrayEnumerable.prototype.Any = function (predicate) 2316 { 2317 return (predicate == null) 2318 ? (this.source.length > 0) 2319 : Enumerable.prototype.Any.apply(this, arguments); 2320 } 2321 2322 ArrayEnumerable.prototype.Count = function (predicate) 2323 { 2324 return (predicate == null) 2325 ? this.source.length 2326 : Enumerable.prototype.Count.apply(this, arguments); 2327 } 2328 2329 ArrayEnumerable.prototype.ElementAt = function (index) 2330 { 2331 return (0 <= index && index < this.source.length) 2332 ? this.source[index] 2333 : Enumerable.prototype.ElementAt.apply(this, arguments); 2334 } 2335 2336 ArrayEnumerable.prototype.ElementAtOrDefault = function (index, defaultValue) 2337 { 2338 return (0 <= index && index < this.source.length) 2339 ? this.source[index] 2340 : defaultValue; 2341 } 2342 2343 ArrayEnumerable.prototype.First = function (predicate) 2344 { 2345 return (predicate == null && this.source.length > 0) 2346 ? this.source[0] 2347 : Enumerable.prototype.First.apply(this, arguments); 2348 } 2349 2350 ArrayEnumerable.prototype.FirstOrDefault = function (defaultValue, predicate) 2351 { 2352 if (predicate != null) 2353 { 2354 return Enumerable.prototype.FirstOrDefault.apply(this, arguments); 2355 } 2356 2357 return this.source.length > 0 ? this.source[0] : defaultValue; 2358 } 2359 2360 ArrayEnumerable.prototype.Last = function (predicate) 2361 { 2362 return (predicate == null && this.source.length > 0) 2363 ? this.source[this.source.length - 1] 2364 : Enumerable.prototype.Last.apply(this, arguments); 2365 } 2366 2367 ArrayEnumerable.prototype.LastOrDefault = function (defaultValue, predicate) 2368 { 2369 if (predicate != null) 2370 { 2371 return Enumerable.prototype.LastOrDefault.apply(this, arguments); 2372 } 2373 2374 return this.source.length > 0 ? this.source[this.source.length - 1] : defaultValue; 2375 } 2376 2377 ArrayEnumerable.prototype.Skip = function (count) 2378 { 2379 var source = this.source; 2380 2381 return new Enumerable(function () 2382 { 2383 var index; 2384 2385 return new IEnumerator( 2386 function () { index = (count < 0) ? 0 : count }, 2387 function () 2388 { 2389 return (index < source.length) 2390 ? this.Yield(source[index++]) 2391 : false; 2392 }, 2393 Functions.Blank); 2394 }); 2395 }; 2396 2397 ArrayEnumerable.prototype.TakeExceptLast = function (count) 2398 { 2399 if (count == null) count = 1; 2400 return this.Take(this.source.length - count); 2401 } 2402 2403 ArrayEnumerable.prototype.TakeFromLast = function (count) 2404 { 2405 return this.Skip(this.source.length - count); 2406 } 2407 2408 ArrayEnumerable.prototype.Reverse = function () 2409 { 2410 var source = this.source; 2411 2412 return new Enumerable(function () 2413 { 2414 var index; 2415 2416 return new IEnumerator( 2417 function () 2418 { 2419 index = source.length; 2420 }, 2421 function () 2422 { 2423 return (index > 0) 2424 ? this.Yield(source[--index]) 2425 : false; 2426 }, 2427 Functions.Blank) 2428 }); 2429 } 2430 2431 ArrayEnumerable.prototype.SequenceEqual = function (second, compareSelector) 2432 { 2433 if ((second instanceof ArrayEnumerable || second instanceof Array) 2434 && compareSelector == null 2435 && Enumerable.From(second).Count() != this.Count()) 2436 { 2437 return false; 2438 } 2439 2440 return Enumerable.prototype.SequenceEqual.apply(this, arguments); 2441 } 2442 2443 ArrayEnumerable.prototype.ToString = function (separator, selector) 2444 { 2445 if (selector != null || !(this.source instanceof Array)) 2446 { 2447 return Enumerable.prototype.ToString.apply(this, arguments); 2448 } 2449 2450 if (separator == null) separator = ""; 2451 return this.source.join(separator); 2452 } 2453 2454 ArrayEnumerable.prototype.GetEnumerator = function () 2455 { 2456 var source = this.source; 2457 var index = 0; 2458 2459 return new IEnumerator( 2460 Functions.Blank, 2461 function () 2462 { 2463 return (index < source.length) 2464 ? this.Yield(source[index++]) 2465 : false; 2466 }, 2467 Functions.Blank); 2468 } 2469 2470 // Collections 2471 2472 var Dictionary = (function () 2473 { 2474 // static utility methods 2475 var HasOwnProperty = function (target, key) 2476 { 2477 return Object.prototype.hasOwnProperty.call(target, key); 2478 } 2479 2480 var ComputeHashCode = function (obj) 2481 { 2482 if (obj === null) return "null"; 2483 if (obj === undefined) return "undefined"; 2484 2485 return (typeof obj.toString === Types.Function) 2486 ? obj.toString() 2487 : Object.prototype.toString.call(obj); 2488 } 2489 2490 // LinkedList for Dictionary 2491 var HashEntry = function (key, value) 2492 { 2493 this.Key = key; 2494 this.Value = value; 2495 this.Prev = null; 2496 this.Next = null; 2497 } 2498 2499 var EntryList = function () 2500 { 2501 this.First = null; 2502 this.Last = null; 2503 } 2504 EntryList.prototype = 2505 { 2506 AddLast: function (entry) 2507 { 2508 if (this.Last != null) 2509 { 2510 this.Last.Next = entry; 2511 entry.Prev = this.Last; 2512 this.Last = entry; 2513 } 2514 else this.First = this.Last = entry; 2515 }, 2516 2517 Replace: function (entry, newEntry) 2518 { 2519 if (entry.Prev != null) 2520 { 2521 entry.Prev.Next = newEntry; 2522 newEntry.Prev = entry.Prev; 2523 } 2524 else this.First = newEntry; 2525 2526 if (entry.Next != null) 2527 { 2528 entry.Next.Prev = newEntry; 2529 newEntry.Next = entry.Next; 2530 } 2531 else this.Last = newEntry; 2532 2533 }, 2534 2535 Remove: function (entry) 2536 { 2537 if (entry.Prev != null) entry.Prev.Next = entry.Next; 2538 else this.First = entry.Next; 2539 2540 if (entry.Next != null) entry.Next.Prev = entry.Prev; 2541 else this.Last = entry.Prev; 2542 } 2543 } 2544 2545 // Overload:function() 2546 // Overload:function(compareSelector) 2547 var Dictionary = function (compareSelector) 2548 { 2549 this.count = 0; 2550 this.entryList = new EntryList(); 2551 this.buckets = {};
2551 // as Dictionary<string,List<object>> 2552 this.compareSelector = (compareSelector == null) ? Functions.Identity : compareSelector; 2553 } 2554 2555 Dictionary.prototype = 2556 { 2557 Add: function (key, value) 2558 { 2559 var compareKey = this.compareSelector(key); 2560 var hash = ComputeHashCode(compareKey); 2561 var entry = new HashEntry(key, value); 2562 if (HasOwnProperty(this.buckets, hash)) 2563 { 2564 var array = this.buckets[hash]; 2565 for (var i = 0; i < array.length; i++) 2566 { 2567 if (this.compareSelector(array[i].Key) === compareKey) 2568 { 2569 this.entryList.Replace(array[i], entry); 2570 array[i] = entry; 2571 return; 2572 } 2573 } 2574 array.push(entry); 2575 } 2576 else 2577 { 2578 this.buckets[hash] = [entry]; 2579 } 2580 this.count++; 2581 this.entryList.AddLast(entry); 2582 }, 2583 2584 Get: function (key) 2585 { 2586 var compareKey = this.compareSelector(key); 2587 var hash = ComputeHashCode(compareKey); 2588 if (!HasOwnProperty(this.buckets, hash)) return undefined; 2589 2590 var array = this.buckets[hash]; 2591 for (var i = 0; i < array.length; i++) 2592 { 2593 var entry = array[i]; 2594 if (this.compareSelector(entry.Key) === compareKey) return entry.Value; 2595 } 2596 return undefined; 2597 }, 2598 2599 Set: function (key, value) 2600 { 2601 var compareKey = this.compareSelector(key); 2602 var hash = ComputeHashCode(compareKey); 2603 if (HasOwnProperty(this.buckets, hash)) 2604 { 2605 var array = this.buckets[hash]; 2606 for (var i = 0; i < array.length; i++) 2607 { 2608 if (this.compareSelector(array[i].Key) === compareKey) 2609 { 2610 var newEntry = new HashEntry(key, value); 2611 this.entryList.Replace(array[i], newEntry); 2612 array[i] = newEntry; 2613 return true; 2614 } 2615 } 2616 } 2617 return false; 2618 }, 2619 2620 Contains: function (key) 2621 { 2622 var compareKey = this.compareSelector(key); 2623 var hash = ComputeHashCode(compareKey); 2624 if (!HasOwnProperty(this.buckets, hash)) return false; 2625 2626 var array = this.buckets[hash]; 2627 for (var i = 0; i < array.length; i++) 2628 { 2629 if (this.compareSelector(array[i].Key) === compareKey) return true; 2630 } 2631 return false; 2632 }, 2633 2634 Clear: function () 2635 { 2636 this.count = 0; 2637 this.buckets = {}; 2638 this.entryList = new EntryList(); 2639 }, 2640 2641 Remove: function (key) 2642 { 2643 var compareKey = this.compareSelector(key); 2644 var hash = ComputeHashCode(compareKey); 2645 if (!HasOwnProperty(this.buckets, hash)) return; 2646 2647 var array = this.buckets[hash]; 2648 for (var i = 0; i < array.length; i++) 2649 { 2650 if (this.compareSelector(array[i].Key) === compareKey) 2651 { 2652 this.entryList.Remove(array[i]); 2653 array.splice(i, 1); 2654 if (array.length == 0) delete this.buckets[hash]; 2655 this.count--; 2656 return; 2657 } 2658 } 2659 }, 2660 2661 Count: function () 2662 { 2663 return this.count; 2664 }, 2665 2666 ToEnumerable: function () 2667 { 2668 var self = this; 2669 return new Enumerable(function () 2670 { 2671 var currentEntry; 2672 2673 return new IEnumerator( 2674 function () { currentEntry = self.entryList.First }, 2675 function () 2676 { 2677 if (currentEntry != null) 2678 { 2679 var result = { Key: currentEntry.Key, Value: currentEntry.Value }; 2680 currentEntry = currentEntry.Next; 2681 return this.Yield(result); 2682 } 2683 return false; 2684 }, 2685 Functions.Blank); 2686 }); 2687 } 2688 } 2689 2690 return Dictionary; 2691 })(); 2692 2693 // dictionary = Dictionary<TKey, TValue[]> 2694 var Lookup = function (dictionary) 2695 { 2696 this.Count = function () 2697 { 2698 return dictionary.Count(); 2699 } 2700 2701 this.Get = function (key) 2702 { 2703 return Enumerable.From(dictionary.Get(key)); 2704 } 2705 2706 this.Contains = function (key) 2707 { 2708 return dictionary.Contains(key); 2709 } 2710 2711 this.ToEnumerable = function () 2712 { 2713 return dictionary.ToEnumerable().Select(function (kvp) 2714 { 2715 return new Grouping(kvp.Key, kvp.Value); 2716 }); 2717 } 2718 } 2719 2720 var Grouping = function (key, elements) 2721 { 2722 this.Key = function () 2723 { 2724 return key; 2725 } 2726 2727 ArrayEnumerable.call(this, elements); 2728 } 2729 Grouping.prototype = new ArrayEnumerable(); 2730 2731 // out to global 2732 return Enumerable; 2733})()
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.