Skip to content

Commit

Permalink
1. Remove flat method, replace it with selectMany(element, result)
Browse files Browse the repository at this point in the history
2. Add resultCreator to fromObject
3. Add ofClass method which replace ofType method which where accepting
a function. Now ofType(Function) accepts a type guard.
4. Add more typescript tests
  • Loading branch information
Indomitable committed Aug 14, 2019
1 parent 983a6b5 commit f8e8715
Show file tree
Hide file tree
Showing 13 changed files with 262 additions and 102 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ jobs:
- yarn --pure-lockfile
script:
- yarn test
- yarn test-ts
- stage: deploy
if: tag IS present
install:
Expand Down
27 changes: 20 additions & 7 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ declare module 'modern-linq' {

/**
* Flat Iterable of collections
* @param map Function which returns a collection
* @param innerSelector Function which returns an inner collection
*/
selectMany<TOutput>(map: (item: TValue) => TOutput[]): LinqIterable<TOutput>;
selectMany<TInner>(innerSelector: (item: TValue) => TInner[]): LinqIterable<TInner>;

/**
* Flat Iterable of collections, where the output is pair of outer and inner element
* @param map Function which returns a collection
* Flat iterable of collection
* @param innerSelector Function which returns an inner collection
* @param resultCreator Function thish converts pair of outer and inner element to result.
*/
flat<TOutput>(map: (item: TValue) => TOutput[]): LinqIterable<{ outer: TValue, inner: TOutput }>;

selectMany<TInner, TResult>(innerSelector: (item: TValue) => TInner[], resultCreator: (outer: TValue, inner: TInner) => TResult): LinqIterable<TResult>;
/**
* Take first N items from iterable
* @param count
Expand Down Expand Up @@ -94,7 +94,13 @@ declare module 'modern-linq' {
* Selects all items of base type
* @param type
*/
ofType<TOutput extends TValue>(type: { prototype: TOutput }): LinqIterable<TOutput>;
ofType<TOutput extends TValue>(typeCheck: (item: TValue) => item is TOutput): LinqIterable<TOutput>;

/**
* Selects all items of base type
* @param type
*/
ofClass<TOutput extends TValue>(type: { prototype: TOutput }): LinqIterable<TOutput>;

/**
* Group items
Expand Down Expand Up @@ -343,6 +349,13 @@ declare module 'modern-linq' {
*/
export function fromObject<TValue extends {}, TKey extends keyof TValue>(value: TValue): LinqIterable<{ key: string, value: TValue[TKey] }>;

/**
* Creates a select js iterable from an object resolving keys using Object.keys(). Returns enumerable keys.
* @param value
* @return sequence of key/value object.
*/
export function fromObject<TValue extends {}, TKey extends keyof TValue, TResult>(value: TValue, resultCreator: (key: TKey, value: TValue[TKey]) => TResult): LinqIterable<TResult>;

/**
* Creates linq iterable from array like object
* @param arrayLike
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
"types": "index.d.ts",
"scripts": {
"build": "rollup -c ./rollup.config.js",
"test": "mocha --require @babel/register test/unit/*.spec.js",
"test-ts": "tsc -p ./test/ts/tsconfig.json && mocha --require @babel/register test/ts/*.spec.js && rm test/ts/*.spec.js",
"test-js": "mocha --require @babel/register test/unit/*.spec.js",
"test-ts": " tsc -p ./test/ts/tsconfig.json && mocha --require @babel/register test/ts/*.spec.js && rm test/ts/*.spec.js",
"test": "yarn test-js && yarn test-ts",
"benchmark": "node --experimental-modules --es-module-specifier-resolution=node test/benchmark"
},
"repository": {
Expand Down
21 changes: 14 additions & 7 deletions src/creation.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { RangeIterable } from "./generators/range";
import { BaseLinqIterable } from "./base-linq-iterable";
import { RepeatIterable } from "./generators/repeat";
import { doneValue, iteratorResultCreator } from "./utils";

export class LinqIterable extends BaseLinqIterable {
constructor(source) {
Expand Down Expand Up @@ -37,22 +38,28 @@ export class ArrayLikeIterable extends BaseLinqIterable {
if (current < length) {
const value = source[current];
current++;
return { done: false, value };
return iteratorResultCreator(value);
} else {
return { done: true };
return doneValue();
}
}
};
}
}

export class ObjectIterable extends BaseLinqIterable {
constructor(source) {
constructor(source, resultCreator) {
super(source);
this.resultCreator = typeof resultCreator === 'undefined' ? ObjectIterable.__defaultResultCreator : resultCreator;
}

static __defaultResultCreator(key, value) {
return { key, value };
}

[Symbol.iterator]() {
const obj = this.source;
const resultCreator = this.resultCreator;
const keys = Object.keys(obj);
let index = 0;
return {
Expand All @@ -61,9 +68,9 @@ export class ObjectIterable extends BaseLinqIterable {
const key = keys[index];
const value = obj[key];
index++;
return { done: false, value: { key, value } };
return iteratorResultCreator(resultCreator(key, value));
} else {
return { done: true };
return doneValue();
}
}
};
Expand All @@ -74,8 +81,8 @@ export function fromIterable(source) {
return new LinqIterable(source);
}

export function fromObject(obj) {
return new ObjectIterable(obj);
export function fromObject(obj, resultCreator) {
return new ObjectIterable(obj, resultCreator);
}

/**
Expand Down
2 changes: 0 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { GroupJoinIterable } from "./iterables/group-join";
import { JoinIterable } from "./iterables/join";
import { RepeatIterable } from "./generators/repeat";
import { PageIterable } from "./iterables/page";
import { FlatIterable } from "./iterables/flat";
import { ReverseIterable } from "./iterables/reverse";

// note: if using class as output we can just apply the mixin to BaseLinqIterable.
Expand All @@ -27,7 +26,6 @@ applyMixin(linqMixin, [
WhereIterable,
SelectIterable,
SelectManyIterable,
FlatIterable,
TakeIterable,
SkipIterable,
RangeIterable,
Expand Down
34 changes: 0 additions & 34 deletions src/iterables/flat.js

This file was deleted.

14 changes: 6 additions & 8 deletions src/iterables/join.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BaseLinqIterable } from "../base-linq-iterable";
import { GroupIterable } from "./group";
import { SelectManyIterable } from "./select-many";
import { defaultElementSelector } from "../utils";
import { defaultElementSelector, doneValue, iteratorResultCreator } from "../utils";

export class JoinIterable extends BaseLinqIterable {
/**
Expand Down Expand Up @@ -32,14 +32,12 @@ export class JoinIterable extends BaseLinqIterable {
return {
next() {
const item = SelectManyIterable.__getNextItem(outerIterator, innerItemsExtractor, currentState);
if (item.value.done) {
return item.value;
if (item.done) {
return doneValue();
} else {
currentState = item.currentState;
return iteratorResultCreator(resultCreator(currentState.outerValue, item.innerValue));
}
currentState = item.currentState;
return {
done: false,
value: resultCreator(currentState.outerValue, item.value.value)
};
}
};
}
Expand Down
32 changes: 21 additions & 11 deletions src/iterables/select-many.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BaseLinqIterable } from "../base-linq-iterable";
import { getIterator } from "../utils";
import { getIterator, doneValue, iteratorResultCreator } from "../utils";

/**
* Return flatten mapped array [[1, 2], [3, 4]].selectMany(x => x) === [1, 2, 3, 4, 5]
Expand All @@ -10,21 +10,31 @@ export class SelectManyIterable extends BaseLinqIterable {
* @param {Iterable} source
* @param {Function} extract
*/
constructor(source, extract) {
constructor(source, innerSelector, resultCreator) {
super(source);
this.extract = extract;
this.innerSelector = innerSelector;
this.resultCreator = typeof resultCreator === 'undefined' ? SelectManyIterable.__defaultResultCreator : resultCreator;
}

static __defaultResultCreator(outer, inner) {
return inner;
}

[Symbol.iterator]() {
const source = this._getSource();
const iterator = this._getIterator(source);
const extract = this.extract;
let currentState = null;
const innerSelector = this.innerSelector;
const resultCreator = this.resultCreator;
let currentState = null;
return {
next() {
const item = SelectManyIterable.__getNextItem(iterator, extract, currentState);
currentState = item.currentState;
return item.value;
const item = SelectManyIterable.__getNextItem(iterator, innerSelector, currentState);
if (item.done) {
return doneValue();
} else {
currentState = item.currentState;
return iteratorResultCreator(resultCreator(currentState.outerValue, item.innerValue));
}
}
};
}
Expand Down Expand Up @@ -55,10 +65,10 @@ export class SelectManyIterable extends BaseLinqIterable {
if (!currentState) {
const { current, firstInnerItem, final } = SelectManyIterable.__getInnerIterator(mainIterator, extract);
if (final) {
return { value: { done: true } };
return { done: true };
}
return {
value: { done: false, value: firstInnerItem },
innerValue: firstInnerItem,
currentState: {
innerIterator: current.innerIterator,
outerValue: current.outerValue
Expand All @@ -70,7 +80,7 @@ export class SelectManyIterable extends BaseLinqIterable {
return SelectManyIterable.__getNextItem(mainIterator, extract, null);
}
return {
value: { done: false, value: innerNext.value },
innerValue: innerNext.value,
currentState: {
innerIterator: currentState.innerIterator,
outerValue: currentState.outerValue
Expand Down
17 changes: 8 additions & 9 deletions src/linq-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { JoinIterable } from "./iterables/join";
import { EqualFinalizer } from "./finalizers/equal";
import { PageIterable } from "./iterables/page";
import { defaultSortComparer } from "./utils";
import { FlatIterable } from "./iterables/flat";
import { ReverseIterable } from "./iterables/reverse";

export const linqMixin = {
Expand All @@ -32,11 +31,8 @@ export const linqMixin = {
select(map) {
return new SelectIterable(this, map);
},
selectMany(map) {
return new SelectManyIterable(this, map);
},
flat(selector) {
return new FlatIterable(this, selector);
selectMany(innerSelector, resultCreator) {
return new SelectManyIterable(this, innerSelector, resultCreator);
},
take(count) {
return new TakeIterable(this, count);
Expand All @@ -53,11 +49,14 @@ export const linqMixin = {
return typeof item === type;
});
} else {
return new WhereIterable(this, function (item) {
return item instanceof type;
});
return new WhereIterable(this, type);
}
},
ofClass(classType) {
return new WhereIterable(this, function (item) {
return item instanceof classType;
});
},
groupBy(keySelector, elementSelector, resultCreator) {
return new GroupIterable(this, keySelector, elementSelector, resultCreator);
},
Expand Down
Loading

0 comments on commit f8e8715

Please sign in to comment.