mini-linq.js
Description
LINQ for JavaScript library, which allows to work with arrays in a more easy way and focus on business logic.
Installation
Download and link manually. Or install it
bower install mini-linq-js --save
npm install mini-linq-js --save
Usage
Just link mini-linq.js
or mini-linq.min.js
in your html.
<script type="text/javascript" src="mini-linq.min.js"></script>
You can also attach and use mini-linq with knockout observableArray. Just link mini-linq.knockout.js
.
Also you may use postponed lazy-execution for arrays by linking mini-linq.lazy.js
.
You also may use it in your Node.JS project by using
require('mini-linq-js');
Available methods
Terms
- Predicate - function which accepts arguments (value, index, array) and returns:
true
if arguments matches specified business-logic conditions; false
otherwise; - Selector - function which accepts arguments (value, index, array) and returns some value which should be used instead of original value.
- Comparator - function which accepts two arguments and returns
true
if two arguments are equal and false
otherwise. - Order comparator - function which accepts two arguments and returns:
1
if first argument is greater then second; -1
if second argument is greater then first; 0
if they are equal.
Predicates, selectors, comparators can be written in 3 ways:
- usual way:
function(arg) { return arg * 2; }
; - modern way (by using arrow functions):
arg => arg * 2
; - modern way with obsolete browsers support:
'arg => arg * 2'
. It's almost the same as in p.2, just wrapped as a string. mini-linq core will parse this string and generated appropriate function. Important! It's not possible to use closure variables using this way.
Methods description
Description:
.any
checks if there is at least one element in array which matches predicate. If called without predicate then it checks for any element in the array.
Arguments:
.any
accepts predicate or nothing.
Returns:
true
if there is at least one element which matches specified predicate; false
otherwise.
Example of usage:
[1, 2, 3].any();
[1, 2, 3].any(a => a > 2);
[1, 2, 3].any(a => a < 0);
[].any();
Description:
.all
checks if all elements in array match predicate.
Arguments:
.all
accepts predicate.
Returns:
true
if all elements match specified predicate; false
otherwise.
Example of usage:
[1, 2, 3].all(a => a > 0);
[1, 2, 3].all(a => a > 2);
Description:
.where
selects all elements which match predicate.
Arguments:
.where
accepts predicate.
Returns:
Array of elements which match predicate. Or empty array if there are no such elements.
Example of usage:
[1, 2, 3, 4].where(a => a > 2);
[1, 2, 3, 4].where(a => a > 5);
Description:
.select
produces new array by applying selector for each element.
Arguments:
.select
accepts selector.
Returns:
Array of elements produced by applying selector. Or empty array if there are no elements.
Example of usage:
[1, 2, 3, 4].select(s => s * 10);
[].select(a => a * 10);
Description:
.selectMany
produces new array by applying selector for each element and combining selected arrays together into one single array.
Arguments:
.selectMany
accepts selector.
Returns:
Array of elements produced by applying selector. Or empty array if there are no elements.
Example of usage:
var testArray = [
{ x: [1, 2], y: 0 },
{ x: [3, 4], y: 1 },
{ x: [5, 6], y: 2 }];
testArray.selectMany(sm => sm.x);
testArray.selectMany(sm => sm.y);
Description:
.count
calculates count of elements which match predicate. If called without predicate then it will return total count of elements.
Arguments:
.count
accepts predicate or nothing.
Returns:
Count of elements which match specified predicate. Or total count of elements if predicate is not specified.
Example of usage:
[1, 2, 3, 4].count(s => c > 2);
[1, 2, 3, 4].count();
Description:
.orderBy
order elements in ascending order by using selector and order comparator (if specified).
Arguments:
.orderBy
accepts selector as first argument and may accept order comparator as a second argument.
Returns:
Array of ordered elements.
Example of usage:
[2, 1, 4, 3].orderBy(s => s);
[2, 1, 4, 3].orderBy(s => s, (first, second) => first - second);
Description:
.orderByDescending
order elements in descending order by using selector and order comparator (if specified).
Arguments:
.orderByDescending
accepts selector as first argument and may accept order comparator as a second argument.
Returns:
Array of ordered elements.
Example of usage:
[2, 1, 4, 3].orderByDescending(s => s);
[2, 1, 4, 3].orderByDescending(s => s, (first, second) => first - second);
Description:
.groupBy
group elements by specified selector as a key.
Arguments:
.groupBy
accepts selector as first argument and may accept result selector as a second argument. If result selector is not specified then (group, values) => { group: group, values: values }
selector will be used.
Returns:
Array of grouped elements.
Example of usage:
[2, 1, 4, 3, 5, 6].groupBy(s => s % 2);
[2, 1, 4, 3, 5, 6].groupBy(s => s % 2, (group, values) => (group == 0 ? 'even: ' : 'odd: ') + values);
Description:
.distinct
selects distinct elements by using selector as a key or element if selector is not specified.
Arguments:
.distinct
may accept selector.
Returns:
Array of distinct elements.
Example of usage:
[2, 1, 2, 3, 1, 6, 7, 3, 2].distinct();
[2, 1, 2, 3, 1, 6, 7, 3, 2].distinct(d => d % 3)
Description:
.firstOrDefault
selects first element which matches predicate if there is not such element, then null
will be returned. If predicate is not specified then first element will be returned or null
if array is empty.
Arguments:
.firstOrDefault
may accept predicate.
Returns:
First element which matches predicate or null
if there is no such element. If predicate is not specified then first element will be returned or null
if array is empty.
Example of usage:
[2, 1, 2, 3, 1, 6, 7, 3, 2].firstOrDefault(f => f % 2 == 1);
[2, 1, 2, 3, 1, 6, 7, 3, 2].firstOrDefault()
[2, 1, 2, 3, 1, 6, 7, 3, 2].firstOrDefault(f => f < 0)
[].firstOrDefault()
Description:
.lastOrDefault
selects last element which matches predicate if there is not such element, then null
will be returned. If predicate is not specified then last element will be returned or null
if array is empty.
Arguments:
.lastOrDefault
may accept predicate.
Returns:
Last element which matches predicate or null
if there is no such element. If predicate is not specified then last element will be returned or null
if array is empty.
Example of usage:
[2, 1, 2, 3, 1, 6, 7, 3, 2].lastOrDefault(f => f % 2 == 1);
[2, 1, 2, 3, 1, 6, 7, 3, 9].lastOrDefault()
[2, 1, 2, 3, 1, 6, 7, 3, 2].lastOrDefault(f => f < 0)
[].lastOrDefault()
Description:
.joinWith
combines two arrays based upon the inner key selector and outer key selector.
Arguments:
.joinWith
accepts following arguments (1-4 are mandatory, 5-th is optional):
- inner array to join with;
- inner key selector which will be applied to inner array elements;
- outer key selector which will be applied to outer array elements;
- result selector which should accept two arguments (inner element and outer element) and return result element;
- key comparator which implements comparation logic between inner key and outer key. (optional)
Returns:
Array of combined elements.
Example of usage:
[1, 2, 8, 2, 6, 3, 9, 2, 4].joinWith([1, 2, 3, 4], 'ik => ik', 'ok => ok', '(i, o) => i');
[1, 2, 3].joinWith([4, 5, 6], ik => true, ok => true, (i, o) => '' + i + o);
[1, 2, 3].joinWith([1, 2, 3], ik => ik + 1, ok => ok, (i, o) => i);
[1, 2, 3].joinWith([4, 5, 6], ik => ik, ok => ok, (i, o) => i)
Description:
.groupJoinWith
correlates the elements of two arrays based on equality of keys and groups the results.
Arguments:
.groupJoinWith
accepts following arguments (1-4 are mandatory, 5-th is optional):
- inner array to join with;
- inner key selector which will be applied to inner array elements;
- outer key selector which will be applied to outer array elements;
- result selector which should accept two arguments (array of matched inner element and outer element) and return result element;
- key comparator which implements comparation logic between inner key and outer key. (optional)
Returns:
Array of combined elements.
Example of usage:
[1, 2, 3, 4].groupJoinWith([1, 2, 3, 1, 2, 3], 'ik => ik', 'ok => ok', '(g, o) => g');
[1, 2, 3, 4].groupJoinWith([], 'ik => ik', 'ok => ok', '(g, o) => o');
[].groupJoinWith([1, 2, 3, 1, 2, 3], 'ik => ik', 'ok => ok', '(g, o) => g');
Description:
.contains
checks if passed value presents in array.
Arguments:
.contains
accepts value and may accept comparator as a second argument. If comparator is not passed then (a, b) => a === b
comparator will be used by default.
Returns:
true
if value presents in array; false
otherwise.
Example of usage:
[1, 2, 3, 4].contains(3);
[1, 2, 3, 4].contains(5);
[1, 2, 3, 4].contains('2');
[1, 2, 3, 4].contains('2', (a, b) => a == b);
Description:
.aggregate
applies an accumulator function over a sequence. It acts the same as Array.prototype.reduce
.
Arguments:
.aggregate
accepts accumulator function, which should accept two arguments: previous result and current element. Also may accept initial value as a second argument.
Returns:
Aggregated result.
Example of usage:
[1, 2, 3, 4].aggregate((c, n) => c + n);
[1, 2, 3, 4].aggregate((c, n) => c + n, 10);
[].aggregate((c, n) => c + n);
[].aggregate((c, n) => c + n, 0);
Description:
.sum
calculates total sum of elements using selector if specified.
Arguments:
.sum
may accept selector.
Returns:
Total sum.
Example of usage:
[1, 2, 3, 4].sum();
[1, 2, 3, 4].sum(s => s);
[1, 2, 3, 4].sum(s => s * 10);
Description:
.min
finds minimum value using selector if specified.
Arguments:
.min
may accept selector.
Returns:
Minimum value. Or undefined
if array is empty.
Example of usage:
"the quick brown fox jumps over the lazy dog".split(' ').min('s => s.length');
[].min();
[9, 5, 1, 9, 3, 5, 6].min();
Description:
.max
finds maximum value using selector if specified.
Arguments:
.max
may accept selector.
Returns:
Maximum value. Or undefined
if array is empty.
Example of usage:
"the quick brown fox jumps over the lazy dog".split(' ').max('s => s.length');
[].max();
[9, 5, 1, 9, 3, 5, 6].max();
Description:
.skip
skips specified amount of elements.
Arguments:
.skip
accepts number of elements to skip.
Returns:
Array of elements after skipped elements.
Example of usage:
[1, 2, 3, 4].skip(2);
[1, 2, 3, 4].skip(0);
[1, 2, 3, 4].skip(9);
Description:
.take
takes specified amount of elements.
Arguments:
.take
accepts number of elements to take.
Returns:
Array of taken elements.
Example of usage:
[1, 2, 3, 4].take(2);
[1, 2, 3, 4].take(0);
[1, 2, 3, 4].take(9);
Description:
.ofType
filter elements based on specified type. Basically it's a shortcut for .where(w => typeof(w) === specifiedType)
.
Arguments:
.ofType
accepts the type to filter the elements on.
Returns:
Array of elements of specified type.
Example of usage:
[1, '2', '3', 4].ofType('string');
[1, '2', '3', 4].ofType('number');
[1, '2', '3', 4].ofType('object');
Description:
.union
combines two arrays together into single array.
Arguments:
.union
accepts array to combine.
Returns:
Array of elemnts from source arrays.
Example of usage:
[1, 2, 3, 4].union([2, 3, 4, 5]);
[1, 2, 3, 4].union([]);
[].union([]);
By default all mini-linq methods will execute their logic instantly and return result. But in some cases it may be useful to postpone execution, until some conditions take place.
To do this with mini-linq it's necesasry to load mini-linq.lazy.js
module. After that it will be possible to use .toLazy()
to cast array to lazy array. .toLazy()
doesn't accept any argument and returns LazyArray
instance. LazyArray
has the same mini-linq methods as normal array with the exception that some of them are not executing instantly. To get final result array you have to use .toArray()
method. For example:
[1, 2, 3, 4].toLazy();
[1, 2, 3, 4].toLazy().where(w => w > 2);
[1, 2, 3, 4].toLazy().where(w => w > 2).toArray();
LazyArray has some optimization logic, to reduce amount of array traversals, for example:
[1, 2, 3, 4].toLazy().where(w => w > 1).where(w => w < 4).toArray();
Author
Alexander Kopachov (alex.kopachov@gmail.com)
License
MIT