/LINQ-To-JavaScript

LINQ to JavaScript makes you able to filter, project, sort, group and join sequence of elements using the most popular LINQ methods known for .NET Developers like where, select, orderBy, groupBy, innerJoin, ..And a lot more

Primary LanguageJavaScriptMIT LicenseMIT

LINQ to JavaScript

With LINQ to JavaScript, querying javascript's arrays became easy. LINQ to JavaScript is containing many of the most important methods as in C#.NET LINQ to Objects.

LINQ to JavaScript makes you able to filter, project, sort, group and join sequence of elements using the most popular LINQ methods known for .NET Developers like where, select, orderBy, groupBy, innerJoin, ..And a lot more

LINQ to JavaScript extending the Array prototype which means you can directly call methods on an array and it also support chaining so you can call multiple methods in raw as you do with .NET LINQ

LINQ to JavaScript tests written in Jasmine testing framework with all test cases you can find it in Unit Tests folder and the runner is [LinqToJavascriptTestRunner.html]

Note: Arrow functions (lambda functions) was introduced in ECMA 6 Specifications, it's totally new and only new versions of browsers support it. But by the end of the day it's a function so both of codes belows are equivilant.

Arrow Functions Syntax Normal Functions Syntax

  var x = arr.where(o => o.age > 18);


  var x = arr.where(function (o) { return o.age > 18 });

Methods List

I'll start listing the methods included in LINQ to JavaScript library and i'll explain each one with proper examples.

1- where (filter):

Filters a sequence of values based on a predicate.
filter [mandatory] [Type: function, Returns: boolean]: A function to test each element for a condition .

        var numbers = [1,2,3,4,5,6,7,8,9,10];
        numbers = numbers.where(o => o > 5);
        //Result [6,7,8,9,10]
        var objects = [{ name: "Ibrahim", age:25 }, {name: "Nada", age:18}, {name: "Hassan", age:21}];
        objects = objects.where(o=> o.age > 20); 
        //Result [{ name: "Ibrahim", age:25 }, {name: "Hassan", age:21}]
    
	

2- select (selector):

Projects each element of a sequence into a new form.
selector [mandatory] [Type: function, Returns: element.]: A transform function to apply to each element.


    var ar = [{ firstName: "Ibrahim", lastName: "Abdel Kareem", age:25 }, {firstName: "Nada", lastName: "ElNimr", age:20}, {firstName: "Hassan", lastName: "Ahmed", age:21}];
    ar = ar.select(o=> { return { fullName: (o.firstName + " " + o.lastName), age: o.age} }); 
    //Result ar = [{ fullName: "Ibrahim Abdel Kareem", age:25 }, {fullName: "Nada ElNimr", age:20}, {fullName: "Hassan Ahmed", age:21}]

3- firstOrDefault(filter):

[parameter] Returns the first element of the sequence that satisfies a condition or null if no such element is found.
[no parameter] Returns the first element of a sequence, or null if the sequence contains no elements.
filter [optional] [Type: function, Returns: boolean.] A function to test each element for a condition


    var ar = [1,2,3,4,5,6,7,8,9];
    var noParameter = ar.firstOrDefault(); //Result 1
    var withParameter = ar.firstOrDefault(o=> o >7); //Result 8
    var noMatch = ar.firstOrDefault(o=> o >20); //Result null

3- lastOrDefault(filter):

[parameter] Returns the last element of the sequence that satisfies a condition or null if no such element is found.
[no parameter] Returns the last element of a sequence, or null if the sequence contains no elements.
filter [optional] [Type: function, Returns: boolean.] A function to test each element for a condition


    var ar = [1,2,3,4,5,6,7,8,9];
    var noParameter = ar.lastOrDefault(); //Result 9
    var withParameter = ar.lastOrDefault(o=> o < 7); //Result 6
    var noMatch = ar.lastOrDefault(o=> o > 20); //Result null

4- take(number):

Returns a specified number of contiguous elements from the start of a sequence.
number [mandatory] [Type: number] The number of elements to return.


    var ar = [1,2,3,4,5,6,7,8,9];
    ar = ar.take(4); //Result [1,2,3,4]

5- takeWhile(filter):

Returns elements from a sequence as long as a specified condition is true.
filter [mandatory] [Type: function, Returns: boolean.] A function to test each element for a condition.


    var ar = [1,2,3,4,5,6,7,8,9];
    ar = ar.takeWhile(o=> o < 4); //Result [5,6,7,8,9]

6- skip(number):

Bypasses a specified number of elements in a sequence and then returns the remaining elements.
number [mandatory] [Type: number] The number of elements to Bypassed.


    var ar = [1,2,3,4,5,6,7,8,9];
    ar = ar.skip(4); //Result [5,6,7,8,9]

7- skipWhile(filter):

Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements.
filter [mandatory] [Type: function, Returns: boolean.] A function to test each element for a condition.


    var ar = [1,2,3,4,5,6,7,8,9];
    ar = ar.skipWhile(o=> o < 5); //Result [5,6,7,8,9]

8- orderBy(filter):

[no parameter] Sorts the elements of a sequence in ascending order.
[parameter] Sorts the elements of a sequence in ascending order according to a key.
filter [optional] [Type:function, Returns: object] A function that returns a value to be used as the key in sorting.
filter [optional [Type:string] Property name to be used as the key in sorting.

NOTE: filter parameter is optional if the sequence contains primitive types that can be sorted [number, string]. If sequence contains objects then you have to pass string or function to filter parameter as described above.


    var primitiveArray = [2,10,3,7,6,1,8,5,9,4];
    primitiveArray = ar.orderBy(); //Result [1,2,3,4,5,6,7,8,9,10]
    var objectArray = [{ name: "Ibrahim", age:25 }, {name: "Nada", age:18}, {name: "Hassan", age:21}];
    var stringFilter = objectArray.orderBy("age"); //Result: [{name: "Nada", age:18}, {name: "Hassan", age:21}, { name: "Ibrahim", age:25 }]
    var functionFilter = objectArray.orderBy(o=> o.name); //Result: [{name: "Hassan", age:21}, { name: "Ibrahim", age:25 }, {name: "Nada", age:18}]

9- orderByDesc(filter):

[no parameter] Sorts the elements of a sequence in descending order.
[parameter] Sorts the elements of a sequence in descending order according to a key.
filter [optional] [Type:function, Returns: object] A function that returns a value to be used as the key in sorting.
filter [optional [Type:string] Property name to be used as the key in sorting.

NOTE: filter parameter is optional if the sequence contains primitive types that can be sorted [number, string]. If sequence contains objects then you have to pass string or function to filter parameter as described above.


    var primitiveArray = [2,10,3,7,6,1,8,5,9,4];
    primitiveArray = ar.orderBy(); //Result [10,9,8,7,6,5,4,3,2,1]
    var objectArray = [{name: "Nada", age:18}, {name: "Hassan", age:21}, { name: "Ibrahim", age:25 }];
    var stringFilter = objectArray.orderBy("age"); //Result: [{ name: "Ibrahim", age:25 }, {name: "Hassan", age:21}, {name: "Nada", age:18}]
    var functionFilter = objectArray.orderBy(o=> o.name); //Result: [ {name: "Nada", age:18}, { name: "Ibrahim", age:25 }, {name: "Hassan", age:21}]

10 - groupBy(filter):

Groups the elements of a sequence according to a specified key selector function.
filter [mandatory] [Type:function, Returns: object] A function that returns a value to be used as the key in grouping.
filter [mandatory] [Type:string] Property name to be used as the key in grouping.


    var ar = [{name: "Nada", age:18, role:"Admin"}, {name: "Hassan", age:21, role:"User"}, { name: "Ibrahim", age:25, role:"Admin" }];
    var stringFilter = ar.groupBy("role");
    //Result: [{key: "Admin", value: [{name: "Nada", age:18, role:"Admin"},{ name: "Ibrahim", age:25, role:"Admin" }]}]
    var functionFilter = ar.groupBy(o=> o.role);
    //Result: [{key: "Admin", value: [{name: "Nada", age:18, role:"Admin"},{ name: "Ibrahim", age:25, role:"Admin" }]}]

11- removeAt(index):

Remove an element from the array for given index. index [mandatory] [Type:number] The index to remove.


    var ar = [{name: "Nada", age:18, role:"Admin"}, {name: "Hassan", age:21, role:"User"}, { name: "Ibrahim", age:25, role:"Admin" }];
    ar.removeAt(1);
    //Result: [{name: "Nada", age:18, role:"Admin"}, { name: "Ibrahim", age:25, role:"Admin" }];

12- innerJoin(listToJoin, conditionFunction, selectorFunction):

Combines the elements of two sequences based on matching keys.
listToJoin [mandatory] [type:Array] The sequence to join.
conditionFunction [mandatory] [Type:function, Returns:boolean] A function that compare keys of both sequences.
selectorFunction [optional] [Type:function, Returns:object] A function that projects each joined elements of both sequences into a new form (Optional).


    var users = [{ id: 1, firstName: "Ahmed", lastName: "Hassan", age: 18, roleId: 2 }, { id: 2, firstName: "Ibrahim", lastName: "Abdel Kareem", age: 25, roleId: 1 }, { id: 3, firstName: "Nada", lastName: "El Nimr", age: 25, roleId: 1 }, {id:4, firstName: "Mohammed", lastName: "Ahmed", age:28, roleId:3}];
    var roles = [{ id: 1, roleName: "Admin" }, { id: 2, roleName: "User" }];
    var withoutSelector = users.innerJoin(roles, (user,role)=> user.roleId == role.id);
    //Result: [{ id: 1, firstName: "Ahmed", lastName: "Hassan", age: 18, roleId: 2, id1: 2, roleName: "User" }, { id: 2, firstName: "Ibrahim", lastName: "Abdel Kareem", age: 25, roleId: 1, id1: 1, roleName: "Admin" }, { id: 3, firstName: "Nada", lastName: "El Nimr", age: 25, roleId: 1, id1: 1, roleName: "Admin" }]
    NOTE: id1 is the id property in role object and it was named id1 because there's no selectorFunction and there's property with the same name in user object
    var withSelector = users.innerJoin(roles, (user,role)=> user.roleId == role.id, (user,role)=> {return { id: user.id, fullName: (user.firstName + " " + user.lastName), age: user.age, roleId: role.id, roleName: role.roleName }});
    //Result: [{ id: 1, fullName: "Ahmed Hassan", age: 18, roleId: 2, roleName: "User" }, { id: 2, fullName: "Ibrahim Abdel Kareem", age: 25, roleId: 1, roleName: "Admin" }, { id: 3, firstName: "Nada El Nimr", age: 25, roleId: 1, roleName: "Admin" }]

13- leftOuterJoin(listToJoin, conditionFunction, selectorFunction):

Combines the elements of two sequences based on matching keys if matching was found.
listToJoin [mandatory] [Type:Array] The sequence to join.
conditionFunction [mandatory] [Type:function, Returns:boolean] A function that compare keys of both sequences.
selectorFunction [optional] [Type:function, Returns:object] A function that projects each joined elements of both sequences into a new form (Optional).


    var users = [{ id: 1, firstName: "Ahmed", lastName: "Hassan", age: 18, roleId: 2 }, { id: 2, firstName: "Ibrahim", lastName: "Abdel Kareem", age: 25, roleId: 1 }, { id: 3, firstName: "Nada", lastName: "El Nimr", age: 25, roleId: 1 }, {id:4, firstName: "Mohammed", lastName: "Ahmed", age:28, roleId:3}];
    var roles = [{ id: 1, roleName: "Admin" }, { id: 2, roleName: "User" }];
    var withoutSelector = users.leftOuterJoin(roles, (user,role)=> user.roleId == role.id);
    //Result: [{ id: 1, firstName: "Ahmed", lastName: "Hassan", age: 18, roleId: 2, id1: 2, roleName: "User" }, { id: 2, firstName: "Ibrahim", lastName: "Abdel Kareem", age: 25, roleId: 1, id1: 1, roleName: "Admin" }, { id: 3, firstName: "Nada", lastName: "El Nimr", age: 25, roleId: 1, id1: 1, roleName: "Admin" }, , {id:4, firstName: "Mohammed", lastName: "Ahmed", age:28, roleId:3}]
    NOTE: user with id = 4 returned however there's no role for him
    var withSelector = users.leftOuterJoin(roles, (user,role)=> user.roleId == role.id, (user,role)=> {return { id: user.id, fullName: (user.firstName + " " + user.lastName), age: user.age, roleId: role ? role.id : null, roleName: role ? role.roleName : null }});
    //Result: [{ id: 1, fullName: "Ahmed Hassan", age: 18, roleId: 2, roleName: "User" }, { id: 2, fullName: "Ibrahim Abdel Kareem", age: 25, roleId: 1, roleName: "Admin" }, { id: 3, firstName: "Nada El Nimr", age: 25, roleId: 1, roleName: "Admin" }, {id:4, firstName: "Mohammed", lastName: "Ahmed", age:28, roleId: null, roleName: null}]

15- any(filter):

[parameter] Determines whether any element of a sequence satisfies a condition.
[no parameter] Determines whether a sequence contains any elements.
filter [optional] [Type: function, Returns: boolean] A function to test each element for a condition.


    var emptyArray = [];
    var dataArray = [1,2,3,5,6,8];
    var hasData = emptyArray.any(); //Result: false
    var hasData2 = dataArray.any(); //Result: true
    var condition = dataArray.any(o => o > 5); //Result: true

16- all(filter)

Determines whether all element of a sequence satisfies a condition.
filter [mandatory] [Type: function, Returns: boolean] A function to test each element for a condition.


    var dataArray = [1,2,3,5,6,8];
    var falsyCondition = emptyArray.all(o=> o > 5); //Result: false
    var truthyCondition = dataArray.all(o => o < 10); //Result: true

17- max(selector)

Returns the maximum value in the sequence
selector [mandatory] [Type: function, Returns: number] A function to return a number from a sequence element to be used in maximum calculation.


    var numbersArray = [1,74,30,2,95,5,2,33,3,77,4,5,6,7];
    var employeesArray = [{name: "Ahmed", age:18}, {name: "Ibrahim", age: 25}, {name: "Mohamed", age:13}];
    var numberMax = numbersArray.max(o=> o); //Result: 95
    var oldestEmployee = employeesArray.max(o=> o.age); //Result: 25

18- min(selector)

Returns the minimum value in the sequence
selector [mandatory] [Type: function, Returns: number] A function to return a number from a sequence element to be used in maximum calculation.


    var numbersArray = [1,74,30,2,95,5,2,33,3,77,4,5,6,7];
    var employeesArray = [{name: "Ahmed", age:18}, {name: "Ibrahim", age: 25}, {name: "Mohamed", age:13}];
    var numberMin = numbersArray.min(o=> o); //Result: 1
    var youngestEmployee = employeesArray.min(o=> o.age); //Result: 13

19- average(selector)

Returns the average from values in the sequence.
selector [mandatory] [Type: function, Returns: number] A function to return a number from a sequence element to be used in maximum calculation.


    var numbersArray = [1,74,30,2,95,5,2,33,3,77,4,5,6,7];
    var employeesArray = [{name: "Ahmed", age:18}, {name: "Ibrahim", age: 25}, {name: "Mohamed", age:13}];
    var numberAvg = numbersArray.average(o=> o); //Result: 24.571428571428573
    var ageAverage = employeesArray.average(o=> o.age); //Result: 18.666666666666668

Hope you liked the LINQ to JavaScript framework. Appreciating your feedback and suggestions for improvements. Thanks a lot ;)