nativescript-enumerable
Version:
A NativeScript module providing LINQ style extensions for handling arrays and lists.
520 lines (398 loc) • 12.4 kB
Markdown
[](https://www.npmjs.com/package/nativescript-enumerable)
[](https://www.npmjs.com/package/nativescript-enumerable)
A [NativeScript](https://nativescript.org/) module providing [LINQ](https://en.wikipedia.org/wiki/Language_Integrated_Query) style extensions for handling arrays and lists.
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YA4RCT6FQX28J)
This module is part of [nativescript-toolbox](https://github.com/mkloubert/nativescript-toolbox).
[](https://raw.githubusercontent.com/mkloubert/nativescript-enumerable/master/LICENSE)
* Android
* iOS
Run
```bash
tns plugin add nativescript-enumerable
```
inside your app project to install the module.
```typescript
import Enumerable = require("nativescript-enumerable");
// from a list of values / objects with variable length
var seq1 = Enumerable.create(1, 'MK', true, null, {});
// from an array / list
var seq2 = Enumerable.fromArray([11, 22, 33, 44]);
// from object
var seq3 = Enumerable.fromObject({
MK: 23979,
TM: 5979
});
// range of numbers: 2, 3, 4, 5, 6
var seq4 = Enumerable.range(2, 5);
// 50979 'TM' strings
var seq5 = Enumerable.repeat('TM', 50979);
```
```typescript
var seq = Enumerable.create(5979, 23979, null, '23979', 1781, 241279);
var newSeq = seq.where((x) => x !== null) // remove all elements that are (null)
.skip(1) // skip one element (5979)
.take(3) // take next remaining 3 elements (23979, 23979, 1781)
.distinct() // remove duplicates
.select((x) => "" + x) // convert to strings
.order(); // order by element ascending
newSeq.each((item) => {
// [0] 1781
// [1] 23979
console.log(item);
});
```
Most methods are chainable as in [.NET](https://en.wikipedia.org/wiki/.NET_Framework) context.
Many methods require one or more function.
Instead using a function like
```typescript
.where(function(x) {
return x !== null;
})
```
you can write
```typescript
.where('x => x !== null')
```
instead.
The full documentation with all functions and methods can be found on [readme.io](https://nativescript-enumerable.readme.io/docs).
The [demo app](https://github.com/mkloubert/nativescript-enumerable/tree/master/demo) contains examples to all functions and methods.
It also contains a code editor where **you can enter own code and run it!**
<img src="https://raw.githubusercontent.com/mkloubert/nativescript-enumerable/master/images/codeeditor1.png" width="192">
<img src="https://raw.githubusercontent.com/mkloubert/nativescript-enumerable/master/images/codeeditor2.png" width="192">
<img src="https://raw.githubusercontent.com/mkloubert/nativescript-enumerable/master/images/codeeditor3.png" width="192">
The [wiki](https://github.com/mkloubert/nativescript-enumerable/wiki/Demo-app) describes how it works.
```typescript
// distinct()
// 1, 2, 4, 3
Enumerable.create(1, 2, 4, 2, 3)
.distinct();
// except()
// 2.0, 2.1, 2.3, 2.4, 2.5
Enumerable.create(2.0, 2.1, 2.2, 2.3, 2.4, 2.5)
.except([2.2]);
// intersect()
// 26, 30
Enumerable.create(44, 26, 92, 30, 71, 38)
.intersect([30, 59, 83, 47, 26, 4, 3]);
// ofType()
// '2', 'Tanja'
Enumerable.create(1, '2', 2, 'Tanja', 3)
.ofType('string'); // typeof x == 'string'
// union()
// 5, 3, 9, 7, 8, 6, 4, 1, 0
Enumerable.create(5, 3, 9, 7, 5, 9, 3, 7)
.union([8, 3, 6, 4, 4, 9, 1, 0]);
// where()
// 1, 2, 3
Enumerable.create(1, 2, 3, 4)
.where((x) => x < 4);
```
```typescript
// orderBy(), thenBy()
//
// "apple", "grape", "mango", "banana",
// "orange", "blueberry", "raspberry", "passionfruit"
Enumerable.create("grape", "passionfruit", "banana", "mango",
"orange", "raspberry", "apple", "blueberry")
.orderBy((x) => x.length) // complement: orderByDescending()
.thenBy((x) => x); // complement: thenByDescending()
// shorter: then()
// reverse()
// 4, 3, 2, 1
Enumerable.create(1, 2, 3, 4)
.reverse();
```
```typescript
// skip()
// 3, 4
Enumerable.create(0, 1, 2, 3, 4)
.skip(3);
// skipLast()
// 0, 1, 2, 3
Enumerable.create(0, 1, 2, 3, 4)
.skipLast();
// skipWhile()
// 55, 666, 77
Enumerable.create(22, 33, 44, 55, 666, 77)
.skipWhile((x) => x < 50);
// take()
// 0, 1, 2
Enumerable.create(0, 1, 2, 3, 4)
.take(3);
// takeWhile()
// 22, 33, 44
Enumerable.create(22, 33, 44, 55)
.takeWhile((x) => x < 50);
```
```typescript
// elementAt()
// 33
Enumerable.create(11, 22, 33, 44)
.elementAt(2);
// elementAtOrDefault()
// 'TM'
Enumerable.create(11, 22, 33, 44)
.elementAtOrDefault(4, 'TM'); // out of range
// first()
// 11
Enumerable.create(11, 22, 33, 44)
.first();
// firstOrDefault()
// 'MK'
Enumerable.create()
.firstOrDefault('MK');
// last()
// 44
Enumerable.create(11, 22, 33, 44)
.last();
// lastOrDefault()
// 'PZ'
Enumerable.create()
.lastOrDefault('PZ');
// single()
// EXCEPTION, because we have more than one element
Enumerable.create(11, 22, 33, 44)
.single();
// singleOrDefault()
// 11
Enumerable.create(11)
.singleOrDefault('YS');
```
All methods with NO `OrDefault` suffix will throw exceptions if no element was found.
You also can use a function as first argument for all of these methods that works as filter / condition:
```typescript
// first()
// 22
Enumerable.create(11, 22, 33, 44)
.first((x) => x >= 20);
```
```typescript
// aggregate()
// "Marcel Joachim Kloubert"
Enumerable.create('Marcel', 'Joachim', 'Kloubert')
.aggregate((result: string, x: string) => {
return result += " " + x;
});
// average()
// 2.5
Enumerable.create(1, 2, 3, 4)
.average();
// sum()
// 10
Enumerable.create(1, 2, 3, 4)
.sum();
```
```typescript
// max()
// 3
Enumerable.create(1, 3, 2)
.max();
// min()
// 1
Enumerable.create(2, 3, 1, 2)
.min();
```
```typescript
class Person {
constructor(name: string) {
this.name = name;
}
public name: string;
}
class Pet: {
constructor(name: string, owner: Person) {
this.name = name;
this.owner = owner;
}
public name: string;
public owner: Person;
}
var persons: Person[] = [
new Person("Tanja"),
new Person("Marcel"),
new Person("Yvonne"),
new Person("Josefine")
];
var pets: Pet[] = [
new Pet("Gina", persons[1]),
new Pet("Schnuffi", persons[1]),
new Pet("Schnuffel", persons[2]),
new Pet("WauWau", persons[0]),
new Pet("Lulu", persons[3]),
new Pet("Asta", persons[1]),
];
// groupJoin()
//
// [0] 'Owner: Tanja; Pets: WauWau, Sparky'
// [1] 'Owner: Marcel; Pets: Gina, Schnuffi, Asta'
// [2] 'Owner: Yvonne; Pets: Schnuffel'
// [3] 'Owner: Josefine; Pets: Lulu'
Enumerable.fromArray(persons)
.groupJoin(pets,
(person: Person) => person.name,
(pet: Pet) => pet.owner.name,
(person: Person, petsOfPerson: Enumerable.IEnumerable<Pet>) => {
var petList = petsOfPerson
.select((pet: Pet) => pet.name)
.aggregate((result: string, petName: string) => {
return result += ", " + petName;
});
return 'Owner: ' + person.name + '; Pets: ' + petList;
});
// join()
//
// [0] 'Owner: Tanja; Pet: WauWau'
// [1] 'Owner: Marcel; Pet: Gina'
// [2] 'Owner: Marcel; Pet: Schnuffi'
// [3] 'Owner: Marcel; Pet: Asta'
// [4] 'Owner: Yvonne; Pet: Schnuffel'
// [5] 'Owner: Josefine; Pet: Lulu'
Enumerable.fromArray(persons)
.join(pets,
(person: Person) => person.name,
(pet: Pet) => pet.owner.name,
(person: Person, pet: Pet) => {
return 'Owner: ' + person.name + '; Pet: ' + pet.name;
});
```
```typescript
// groupBy()
Enumerable.create("grape", "passionfruit", "banana",
"apple", "blueberry")
.groupBy((x: string) => x[0])
.each(function(grouping: Enumerable.IGrouping<string, string>) {
// grouping[0].key = 'g'
// grouping[0][0] = 'grape'
// grouping[1].key = 'p'
// grouping[1][0] = 'passionfruit'
// grouping[2].key = 'b'
// grouping[2][0] = 'banana'
// grouping[2][1] = 'blueberry'
// grouping[3].key = 'a'
// grouping[3][0] = 'apple'
});
```
```typescript
// select()
// "MARCEL", "KLOUBERT"
Enumerable.create("Marcel", "Kloubert")
.select((x: string) => x.toUpperCase());
// selectMany()
// 1, 10, 100, 2, 20, 200, 3, 30, 300
Enumerable.create(1, 2, 3)
.selectMany((x: number) => [x, x * 10, x * 100]);
// zip()
// "Marcel Kloubert", "Bill Gates", "Albert Einstein"
Enumerable.create('Marcel', 'Bill', 'Albert')
.zip(['Kloubert', 'Gates', 'Einstein', 'Adenauer'],
(firstName: string, lastName: string) => {
return firstName + " " + lastName;
});
```
```typescript
// all()
// (false)
Enumerable.create(1, 2, '3', 4)
.all((x) => typeof x !== "string");
// contains()
// (true)
Enumerable.create(1, 2, '3')
.contains(3);
// any()
// (true)
Enumerable.create(1, 2, '3', 4)
.any((x) => typeof x === "string");
// sequenceEqual()
// (false)
Enumerable.create([1, 2, 3])
.sequenceEqual([1, 3, 2]);
```
```typescript
// toArray()
var jsArray = Enumerable.create(1, 2, 3, 4)
.toArray();
// toObject()
var obj = Enumerable.create(1, 2, 3, 4)
.toObject((item, index) => "item" + index);
// toObservable()
var o = Enumerable.create(1, 2, 3, 4)
.toObservable((item, index) => "item" + index);
// toObservableArray()
var oa = Enumerable.create(1, 2, 3, 4)
.toObservableArray();
// toLookup()
//
// lookup['A'][0] = 'Albert'
// lookup['B'][0] = 'Bill'
// lookup['B'][1] = 'Barney'
// lookup['K'][0] = 'Konrad'
// lookup['M'][0] = 'Marcel'
var lookup = Enumerable.create('Bill', 'Marcel', 'Barney', 'Albert', 'Konrad')
.toLookup((x: string) => x[0]);
```
```typescript
// 3
Enumerable.create(0, 1, 2)
.count();
// 2
Enumerable.create(0, 1, 2)
.count((x) => x > 0);
```
```typescript
// 0, 1, 2, 'PZ', 'TM', 'MK'
Enumerable.create(0, 1, 2)
.concat(['PZ', 'TM', 'MK']);
```
```typescript
// 0, 1, 2
Enumerable.create(0, 1, 2)
.defaultIfEmpty('PZ', 'TM', 'MK');
// 'PZ', 'TM', 'MK'
Enumerable.create()
.defaultIfEmpty('PZ', 'TM', 'MK');
```
```typescript
var seq = Enumerable.create(0, 1, 2);
while (seq.moveNext()) {
console.log(seq.current);
}
```
```typescript
var seq = Enumerable.create(0, 1, 2);
seq.each((x: number) => {
console.log(x);
});
seq.reset()
.each((x: number) => {
console.log(x * 2);
});
```