A familiar set of functions that operate on JavaScript iterables (ES2015+) in a similar way to .NET's LINQ does with enumerables.
for(const e of linq(source)
.filter(a, b, c)) {
// Iterate filtered results.
}
for(const e of linq(source)
.filter(a, b, c)
.transform(x)) {
// Iterate filtered and then transformed results.
}
const result = linq(source)
.filter(a, b, c)
.transform(x)
.resolve(r);
import linq from '@tsdotnet/linq/dist/linq';
import range from '@tsdotnet/linq/dist/iterables/range';
import where from '@tsdotnet/linq/dist/filters/where';
import descending from '@tsdotnet/linq/dist/filters/descending';
const source = range(1,100); // Iterable<number>
const filtered = linq(source).filters(
where(n => n%2===1),
descending);
for(const o of filtered) {
// Emit all odd numbers in descending order.
console.log(o); // 99, 97, 95 ...
}
import {linqExtended, iterables, resolutions} from '@tsdotnet/linq';
const source = iterables.range(1,100); // Iterable<number>
const result = linqExtended(source)
.where(n => n%2===1) // odd numbers only
.resolve(resolutions.sum); // 2500
or
import {linqExtended} from '@tsdotnet/linq';
import {range} from '@tsdotnet/linq/dist/iterables';
import {sum} from '@tsdotnet/linq/dist/resolutions';
const source = iterables.range(1,100); // Iterable<number>
const result = linqExtended(source)
.where(n => n%2===1) // odd numbers only
.resolve(resolutions.sum); // 2500
ES2015 enables full support for the iteration protocol.
Iterables are a significant leap forward in operating with data sequences. Instead of loading entire sets into arrays or other collections, iterables allow for progressive iteration or synchronous streaming of data.
tsdotnet/linq
is designed around iterables but also optimized for arrays.
Iterable<T>
helpers are provided as sources. Calling for an Iterator<T>
should always start from the beginning and iterators are not shared. Same behavior as LINQ in .NET.
empty
, range
, and repeat
to name a few.
See the docs for a full list.
linq(source).filter(a, b);
linq(source).filter(a).filter(b);
Any function that receives an Iterable<T>
and returns an Iterable<T>
is considered an
IterableFilter<T>
. A filter may result in a different order or ultimately a completely different set than the input but must be of the same type.
There are an extensive set of filters. See the docs for a full list.
linq(source).transform(x);
linq(source).filter(a).transform(x);
Any function that receives an Iterable<T>
and returns an Iterable<TResult>
is considered an
IterableValueTransform<T, TResult>
.
Any filter can be used as a transform, but not every transform can be used as a filter.
notNull
, rows
, select
, selectMany
and groupBy
to name a few.
See the docs for a full list.
linq(source).resolve(r);
linq(source).transform(x).resolve(r);
linq(source).filter(a, b).transform(x).resolve(r);
A resolution is a transform that takes an Iterable<T>
and returns TResult
.
Unlike .filter(a)
and .transform(x)
, .resolve(r)
does not wrap the result in another Linq<T>
.
There are an extensive set of resolutions. See the docs for a full list.
Originally this was a port of linq.js
converted to full TypeScript under the name TypeScript.NET Library
and then TypeScript.NET-Core
with full module support but potentially more than a user might want for a simple task. Instead of .NET style extensions, Enumerables
incurred a heavy cost of all the extensions under one module.
Modern web standards and practices demanded more granular access to classes and functions. Hence tsdotnet
was born. tsdotnet/linq
functionally allows for all the features of its predecessor as well as providing type-safety, and most of the features of LINQ in .NET while not forcing the consumer to download unneeded/undesired modules (extensions).