Finally Moved To Git Hub
I have finally pulled the plug and moved the project to GitHub. Come over to Github and contribute to the project! https://github.com/dibiancoj/Linq4Javascript

New Release Up On GitHub...Version 3.0 Which Includes Async Functionality!




Project Description
JLinq.ts(.js) is an implementation of .Net's Linq To Objects. It is built using iterators for complete lazy evaluation to reduce memory and improve performance.

Why I Built This Library
I wanted to learn TypeScript along with building a linq library which had method names and syntax much like the .Net version. I love underscore but I always had to lookup the method name I was looking for.

Features
  • Implement's .Net Linq methods with the same syntax
  • Complete lazy evaluation to reduce memory footprint while improving performance
  • You can use the Typescript file for type safety or use the .js version for plain old Javascript.
  • Drastically outperforms Underscore.js in Chrome, Firefox, and Safari

Samples
//declare my array that I will query
var _Array= [];

    //let's throw some sample data into my array
    for (var i = 0; i < 10; i++) {
        _Array.push({
            id: i,
            txt: i.toString(),
            subArray: [1,2,3]
        });
    }


Let's run a sample where clause (the return value will be a iterator)
var myQuery = _Array.Where(function (x) { return x.id > 5; });


How do I get my results from my query above?
1. Call .ToArray() which will evaluate the results right away and return an array from the where clause
var results = _Array.Where(function (x) { return x.id > 5; }).ToArray();

2. I could also run though the results 1 at a time. This would reduce memory because we never have to materialize a large array when calling ToArray().
//holds the current item of the result set
var CurrentResult ;

while ((CurrentResult = QueryToRun.Next()).CurrentStatus !== ToracTechnologies.JLinq.IteratorStatus.Completed) {
//do something with my result
var myResultItem = CurrentResult.CurrentItem;
}


Chaining Methods
You can chain query methods together. No data will be evaluated until ToArray() or the .Next() method is called.
//this method when ToArray() or .Next() is called would return an array of ints. (id is an int off of my object in the collection)
var myQuery = _Array.Where(function (x) { return x.id > 5; }).Select(function(x){ return { x.id;});

Or I could split my queries such as the following:
//build the start of my query
var myQuery = _Array.Where(function (x) { return x.id > 5; })

//if i have some boolean i want to check.  
if (OnlyTakeTop5Items)
{
      //go sort the items and only take 5 items
      var myResults= myQuery.OrderBy(function(x){ return x.id; }).Take(5).ToArray();
}


Dictionaries
Instead of calling .ToArray() you can push the results to a dictionary. The function passed into the ToDictionary is the dictionary key selector.
var myDictionary = _Array.Where(function (x) { return x.id > 5; }).ToDictionary(function(x){ return x.id;});


A dictionary has the following methods
     ContainsKey(key value to test) - Returns true / false if the key value exists in the dictionary
     Count - Returns int. How many items exist in the dictionary
     GetItem(key value to get) - Returns the value of the dictionary if its exists. Returns null if we can't find the item in the dictionary.
     Keys() - Gets all the keys in the dictionary and returns them. Array Of Keys
     Values() - Gets all the values in the dictionary and returns them. Array Of Values
     GetAllItems() - Gets all the key / value pairs in the dictionary. Array Of TKey and TValue (Key value pair)

Additional Dictionary Information
Dictionaries support a composite key ie: { Id: x.Id, Id2: x.Id2 };
var myDictionary = _Array.Where(function (x) { return x.id > 5; }).ToDictionary(function(x){ return { Id: x.Id, Id2: x.Id2;});


Methods
Below are the list of the rest of the methods we have in the library
Where(function(T) - return boolean): Iterator
var myQuery = _Array.Where(function (x) { return x.id > 5; }).ToArray();

FirstOrDefault(function(T) - return boolean): First Item If Predicate Found, Otherwise Null If Not Found
You can call FirstOrDefault() (with no function) to get the first item (null if not found)
var myFirstItem = _Array.FirstOrDefault(function (x) { return x.id == 5; });

First(function(T) - return boolean): First Item If Predicate Found, Otherwise Error If Not Found
You can call First() (with no function) to get the first item (error if not found)
var myFirstItem = _Array.First(function (x) { return x.id == 5; });

Select(function(T) - New Object): Iterator
var myQuery = _Array.Select(function (x) { return { newId: x.id+1}; }).ToArray();

SelectMany(function(T) - Property Of Collection To Flatten): Iterator
This will select every subArray property. It will flatten everything out.
Example:
    Object 1 = { id: 1, lst: [1,2,3]};
    Object 2 = { id: 2, lst: [4,5,6]};

Results: [1,2,3,4,5,6]

var myQuery = _Array.SelectMany(function (x) { return x.lst;}).ToArray();

Take(number): Iterator
var my2Items= _Array.Where(function (x) { return x.id > 5; }).Take(2).ToArray();

Skip(number): Iterator
var myItems = _Array.Where(function (x) { return x.id > 5; }).Skip(2).ToArray();

Count(): Number
var countOfItems= _Array.Where(function (x) { return x.id > 5; }).Count();

Count(function(T) - returns boolean): Number
_this version of count has a where clause. So anything greater than 10 will be increase the tally_
var countOfItems= _Array.Count(function(x) { return x.id > 10;});

All(function(T) - return boolean): boolean (do all the items in the collection match the predicate)
var myItems = _Array.All(function (x) { return x.id > 5; });

AnyItems(): boolean (do we have any items in the collection)
Depreciated Use Any()
var hasItem = _Array.Where(function (x) { return x.id > 5; }).AnyItems();

Any(function(T) - return boolean) do any items match the predicate
var hasItem = _Array.Where(function (x) { return x.id > 5; }).Any(function(x){ return x.id < 50; });

LastItem(): T returns the last item in the collection
Depreciated Use Last()
var lastItem = _Array.Where(function (x) { return x.id > 5; }).LastItem();

Last(function(T) - return boolean) returns the last item in the collection that matches the predicate
var lastItem = _Array.Last(function(x){ return x.id < 9; });

Distinct(function(T) any)- returns a list of the distinct values of the property passed in
var distinctIds = _Array.Distinct(function(x){ return x.id; }).ToArray();

Min(): number - returns the min number in the collection
var minId =  _Array.Select(function(x){ return x.id; }).Min();

Max(): number - returns the max number in the collection
var maxId =  _Array.Select(function(x){return x.id;}).Max();

Sum(): number - returns the sum of the numbers in the collection
var sumOfIds =  _Array.Select(function(x){ return x.id; }).Sum();

Average(): number - returns the average of the numbers in the collection
var avgerageOfIds =  _Array.Select(function(x){ return x.id; }).Average();

GroupBy(function(T) - return group by property value) returns an array of Keys with an array of items in that key
var groupedData =  _Array.GroupBy(function(x){ return x.id; });


OrderBy(function(T) - return sort property value) returns a sorted array by the property passed in
var sortedData = _Array.Where(function (x) { return x.id > 5; }).OrderBy(Function(x){ return x.id; });

OrderByDescending(function(T) - return sort property value) returns a desc sorted array by the property passed in
var sortedData = _Array.Where(function (x) { return x.id > 5; }).OrderByDescending(Function(x) { return x.id; });

Multi Property Sorting
You can use multiple fields to sort (additional sort columns) by adding the
OrderBy(...).ThenBy(function(x){ return x.Id2;})

Or to secondary sort by desc then use:
OrderBy(...).ThenByDescending(function(x){ return x.Id2;})

You can keep tacking on additional sort columns:
OrderBy(...).ThenBy(function(x){ return x.Id2;}).ThenBy(function(x){return x.Id3;});

Paginate(function(T) - int CurrentPageNumber, int HowManyRecordsPerPage): Array<T>
  var myPagedData= _Array.Paginate(1, 100);

SingleOrDefault(function(T) - return boolean): First Item If Predicate Found, If Multiple Items Are Found Then Error Is Raised. If Nothing Is Found Then Null Is Returned
You can call SingleOrDefault() (with no function) to get the single item (error if not found)
var myFirstItem = _Array.SingleOrDefault(function (x) { return x.id == 5; });

Single(function(T) - return boolean): First Item If Predicate Found, If Multiple Items Are Found Then Error Is Raised. If Nothing Is Found Then Error Is Raised
You can call Single() (with no function) to get the single item (error if not found)
var myFirstItem = _Array.Single(function (x) { return x.id == 5; });

Concat(Array(T) to combine): Iterator - Concat does not removes duplicate values
var myConcatResult = _Array.Concat(_AnotherArray);
or
var myConcatResult = _Array.Where(x => x.Id == 1).Concat(_AnotherArray);

ConcatQuery(Query(T)): Iterator - Concat does not removes duplicate values
var myConcatQuery = _Array.ConcatQuery(_AnotherArray.Where(x => x.Id == 1));
or
var myConcatQuery = _Array.Where(x => x.Id == 1).ConcatQuery(_AnotherArray.Where(x => x.Id == 1));

Union(Array(T) to combine): Iterator - Union removes duplicate values, also does not handle object equality
var myUnionResult = _Array.Union(_AnotherArray);
or
var myUnionResult = _Array.Where(x => x.Id == 1).Union(_AnotherArray);

UnionQuery(Query(T)): Iterator - Union removes duplicate values, also does not handle object equality
var myUnionResult = _Array.UnionQuery(_AnotherArray.Where(x => x.Id == 1));
or
var myUnionResult = _Array.Where(x => x.Id == 1).UnionQuery(_AnotherArray.Where(x => x.Id == 1));

SkipWhile(function(T) - return boolean): Iterator
will Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. "Where" will return everything that meet the condition. SkipWhile will find the first element where the condition is met, and return the rest of the elements
var mySkipWhileResult=  _Array.SkipWhile(function(x){ return x.id > 2; });

TakeWhile(function(T) - return boolean): Iterator
will return all the elements before the test no longer passes. "Where" will return everything that meet the condition. TakeWhile will exit the routine wasn't it doesnt pass the expression
var myTakeWhileResult=  _Array.TakeWhile(function(x){ return x.id > 2; });

Aggregate(function(WorkingT, CurrentT) - return T): Iterator
creates a running total "T" then passes it in for each element
   var QueryToAggregate: Array<number> = [1, 2, 3, 4];

    //go build the query
    var ResultOfQuery = QueryToAggregate.Where(x => x > 2).Aggregate((WorkingT, CurrentT) => WorkingT + CurrentT);


Hash Sets
Instead of pushing things to an array or a dictionary you can push it to a hashset. This uses an object behind the scenes for fast item lookup.
                Push the results to a hashset
                _Array.Where(x => x.Id == 1).ToHashSet();

		ContainsItem(ItemToRetrieve: TValue): boolean - Tries to find the key / object in the hashset

		Add(ValueToAdd: TValue): boolean - Add an item to the hashset. Will return true if it was added. Returns false if it already exists in the hashset

		Values(): Array<TValue>- Gets all the values in the hashset

		Remove(KeyToRemove: TValue) -Removes an item

		BuildHashSet(HashSetDataSource: Iterator<TValue> - Builds a hashset from a Iterator, so if we have an iterator we don't need to materialize that AND a hashset and a key selector

		Count(): number - Gets the count of items in the hashset

Last edited Jul 1, 2015 at 8:42 PM by Torac24, version 57