Skip to content

Commit

Permalink
OrderedEnumerable implements IPartition
Browse files Browse the repository at this point in the history
  • Loading branch information
emonkak committed Mar 21, 2018
1 parent 5d28bb0 commit b8558ae
Show file tree
Hide file tree
Showing 15 changed files with 104 additions and 84 deletions.
4 changes: 2 additions & 2 deletions src/elementAt.ts
@@ -1,8 +1,8 @@
import Partition from './internal/Partition';
import { isPartition } from './internal/partition';
import { noElements } from './internal/errors';

export default function elementAt<TSource>(this: Iterable<TSource>, index: number): TSource {
if (this instanceof Partition) {
if (isPartition(this)) {
return (this as any).elementAt(index);
}
if (Array.isArray(this)) {
Expand Down
4 changes: 2 additions & 2 deletions src/elementAtOrDefault.ts
@@ -1,9 +1,9 @@
import Partition from './internal/Partition';
import { isPartition } from './internal/partition';

export default function elementAtOrDefault<TSource>(this: Iterable<TSource>, index: number): TSource | null;
export default function elementAtOrDefault<TSource>(this: Iterable<TSource>, index: number, defaultValue: TSource): TSource;
export default function elementAtOrDefault<TSource>(this: Iterable<TSource>, index: number, defaultValue: TSource | null = null): TSource | null {
if (this instanceof Partition) {
if (isPartition(this)) {
return (this as any).elementAtOrDefault(index, defaultValue);
}
if (Array.isArray(this)) {
Expand Down
4 changes: 2 additions & 2 deletions src/first.ts
@@ -1,4 +1,4 @@
import Partition from './internal/Partition';
import { isPartition } from './internal/partition';
import { noElements } from './internal/errors';

export default function first<TSource>(this: Iterable<TSource>, predicate?: (element: TSource) => boolean): TSource {
Expand All @@ -9,7 +9,7 @@ export default function first<TSource>(this: Iterable<TSource>, predicate?: (ele
}
}
} else {
if (this instanceof Partition) {
if (isPartition(this)) {
return (this as any).first();
}
if (Array.isArray(this)) {
Expand Down
6 changes: 3 additions & 3 deletions src/firstOrDefault.ts
@@ -1,4 +1,4 @@
import Partition from './internal/Partition';
import { isPartition } from './internal/partition';

export default function firstOrDefault<TSource>(this: Iterable<TSource>): TSource | null;
export default function firstOrDefault<TSource>(this: Iterable<TSource>, predicate: (element: TSource) => boolean): TSource | null;
Expand All @@ -11,8 +11,8 @@ export default function firstOrDefault<TSource>(this: Iterable<TSource>, predica
}
}
} else {
if (this instanceof Partition) {
return (this as any).firstOrDefault(defaultValue);
if (isPartition(this)) {
return (this as any).firstOrDefault(null, defaultValue);
}
if (Array.isArray(this)) {
if ((this as any).length > 0) {
Expand Down
24 changes: 12 additions & 12 deletions src/internal/EmptyPartition.ts
@@ -1,24 +1,24 @@
import Partition from './Partition';
import { IPartition, partitionSymbol } from './partition';
import { noElements } from './errors';

export default class EmptyPartition<TElement> extends Partition<TElement> implements Iterator<TElement> {
constructor() {
super();
}

export default class EmptyPartition<TElement> implements IPartition<TElement>, Iterator<TElement> {
[Symbol.iterator](): Iterator<TElement> {
return this;
}

[partitionSymbol](): boolean {
return true;
}

next(): IteratorResult<TElement> {
return { done: true, value: null as any };
}

skip(count: number): Partition<TElement> {
skip(count: number): IPartition<TElement> {
return this;
}

take(count: number): Partition<TElement> {
take(count: number): IPartition<TElement> {
return this;
}

Expand All @@ -37,8 +37,8 @@ export default class EmptyPartition<TElement> extends Partition<TElement> implem
}

firstOrDefault(): TElement | null;
firstOrDefault(defaultValue: TElement): TElement;
firstOrDefault(defaultValue: TElement | null = null): TElement | null {
firstOrDefault(predicate: null, defaultValue: TElement): TElement;
firstOrDefault(predicate?: null, defaultValue: TElement | null = null): TElement | null {
return defaultValue;
}

Expand All @@ -47,8 +47,8 @@ export default class EmptyPartition<TElement> extends Partition<TElement> implem
}

lastOrDefault(): TElement | null;
lastOrDefault(defaultValue: TElement): TElement;
lastOrDefault(defaultValue: TElement | null = null): TElement | null {
lastOrDefault(predicate: null, defaultValue: TElement): TElement;
lastOrDefault(predicate?: null, defaultValue: TElement | null = null): TElement | null {
return defaultValue;
}
}
7 changes: 6 additions & 1 deletion src/internal/OrderedEnumerable.ts
Expand Up @@ -2,11 +2,12 @@ import OrderedPartition from './OrderedPartition';
import partialQuickSort from './partialQuickSort';
import quickSelect from './quickSelect';
import { Enumerable } from './Enumerable';
import { IPartition, partitionSymbol } from './partition';
import { noElements } from './errors';

const defualtComparer: (first: any, second: any) => number = (first, second) => 0;

export default class OrderedEnumerable<TElement, TKey> extends Enumerable<TElement> {
export default class OrderedEnumerable<TElement, TKey> extends Enumerable<TElement> implements IPartition<TElement> {
constructor(_source: Iterable<TElement>,
private readonly _keySelector: (value: TElement) => TKey,
private readonly _descending: boolean,
Expand All @@ -24,6 +25,10 @@ export default class OrderedEnumerable<TElement, TKey> extends Enumerable<TEleme
}
}

[partitionSymbol](): boolean {
return true;
}

thenBy<TKey>(keySelector: (value: TElement) => TKey): OrderedEnumerable<TElement, TKey> {
return new OrderedEnumerable(this._source, keySelector, false, this._getComparer());
}
Expand Down
21 changes: 12 additions & 9 deletions src/internal/OrderedPartition.ts
@@ -1,27 +1,30 @@
import EmptyPartition from './EmptyPartition';
import OrderedEnumerable from './OrderedEnumerable';
import Partition from './Partition';
import { IPartition, partitionSymbol } from './partition';
import { noElements } from './errors';

export default class OrderedPartition<TElement> extends Partition<TElement> {
export default class OrderedPartition<TElement> implements IPartition<TElement> {
constructor(private readonly _source: OrderedEnumerable<TElement, any>,
private readonly _minIndex: number,
private readonly _maxIndex: number) {
super();
}

[Symbol.iterator](): Iterator<TElement> {
return this._source.toArrayInPartition(this._minIndex, this._maxIndex)[Symbol.iterator]();
}

skip(count: number): Partition<TElement> {
[partitionSymbol](): boolean {
return true;
}

skip(count: number): IPartition<TElement> {
const minIndex = this._minIndex + count;
return minIndex > this._maxIndex
? new EmptyPartition<TElement>()
: new OrderedPartition(this._source, minIndex, this._maxIndex);
}

take(count: number): Partition<TElement> {
take(count: number): IPartition<TElement> {
let maxIndex = this._minIndex + count - 1;
if (maxIndex > this._maxIndex) {
maxIndex = this._maxIndex;
Expand All @@ -34,8 +37,8 @@ export default class OrderedPartition<TElement> extends Partition<TElement> {
}

firstOrDefault(): TElement | null;
firstOrDefault(defaultValue: TElement): TElement;
firstOrDefault(defaultValue: TElement | null = null): TElement | null {
firstOrDefault(predicate: null, defaultValue: TElement): TElement;
firstOrDefault(predicate?: null, defaultValue: TElement | null = null): TElement | null {
return this._source.elementAtOrDefault(this._minIndex, defaultValue as TElement);
}

Expand All @@ -44,8 +47,8 @@ export default class OrderedPartition<TElement> extends Partition<TElement> {
}

lastOrDefault(): TElement | null;
lastOrDefault(defaultValue: TElement): TElement;
lastOrDefault(defaultValue: TElement | null = null): TElement | null {
lastOrDefault(predicate: null, defaultValue: TElement): TElement;
lastOrDefault(predicate?: null, defaultValue: TElement | null = null): TElement | null {
return this._source.lastOrDefaultInPartition(this._minIndex, this._maxIndex, defaultValue);
}

Expand Down
24 changes: 0 additions & 24 deletions src/internal/Partition.ts

This file was deleted.

23 changes: 13 additions & 10 deletions src/internal/RangePartition.ts
@@ -1,14 +1,13 @@
import { argumentOutOfRange } from './errors';
import EmptyPartition from './EmptyPartition';
import Partition from './Partition';
import { IPartition, partitionSymbol } from './partition';
import { argumentOutOfRange } from './errors';

export default class RangePartition extends Partition<number> {
export default class RangePartition implements IPartition<number> {
private readonly _start: number;

private readonly _end: number;

constructor(start: number, count: number) {
super();
this._start = start;
this._end = start + count;
}
Expand All @@ -23,14 +22,18 @@ export default class RangePartition extends Partition<number> {
} while (current < end);
}

skip(count: number): Partition<number> {
[partitionSymbol](): boolean {
return true;
}

skip(count: number): IPartition<number> {
if (count >= this._end - this._start) {
return new EmptyPartition<number>();
}
return new RangePartition(this._start + count, this._end - this._start - count);
}

take(count: number): Partition<number> {
take(count: number): IPartition<number> {
const currentCount = this._end - this._start;
return new RangePartition(this._start, count > currentCount ? currentCount : count);
}
Expand All @@ -53,8 +56,8 @@ export default class RangePartition extends Partition<number> {
}

firstOrDefault(): number | null;
firstOrDefault(defaultValue: number): number;
firstOrDefault(defaultValue: number | null = null): number | null {
firstOrDefault(predicate: null, defaultValue: number): number;
firstOrDefault(predicate?: null, defaultValue: number | null = null): number | null {
return this._start;
}

Expand All @@ -63,8 +66,8 @@ export default class RangePartition extends Partition<number> {
}

lastOrDefault(): number | null;
lastOrDefault(defaultValue: number): number;
lastOrDefault(defaultValue: number | null = null): number | null {
lastOrDefault(predicate: null, defaultValue: number): number;
lastOrDefault(predicate?: null, defaultValue: number | null = null): number | null {
return this._end - 1;
}
}
24 changes: 14 additions & 10 deletions src/internal/RepeatPartition.ts
@@ -1,9 +1,9 @@
import EmptyPartition from './EmptyPartition';
import Partition from './Partition';
import { IPartition, partitionSymbol } from './partition';

export default class RepeatPartition<TResult> extends Partition<TResult> {
constructor(private readonly _element: TResult, private readonly _count: number) {
super();
export default class RepeatPartition<TResult> implements IPartition<TResult> {
constructor(private readonly _element: TResult,
private readonly _count: number) {
}

*[Symbol.iterator](): Iterator<TResult> {
Expand All @@ -12,14 +12,18 @@ export default class RepeatPartition<TResult> extends Partition<TResult> {
}
}

skip(count: number): Partition<TResult> {
[partitionSymbol](): boolean {
return true;
}

skip(count: number): IPartition<TResult> {
if (count >= this._count) {
return new EmptyPartition<TResult>();
}
return new RepeatPartition(this._element, this._count - count);
}

take(count: number): Partition<TResult> {
take(count: number): IPartition<TResult> {
return new RepeatPartition(this._element, count > this._count ? this._count : count);
}

Expand All @@ -41,8 +45,8 @@ export default class RepeatPartition<TResult> extends Partition<TResult> {
}

firstOrDefault(): TResult | null;
firstOrDefault(defaultValue: TResult): TResult;
firstOrDefault(defaultValue: TResult | null = null): TResult | null {
firstOrDefault(predicate: null, defaultValue: TResult): TResult;
firstOrDefault(predicate?: null, defaultValue: TResult | null = null): TResult | null {
return this._element;
}

Expand All @@ -51,8 +55,8 @@ export default class RepeatPartition<TResult> extends Partition<TResult> {
}

lastOrDefault(): TResult | null;
lastOrDefault(defaultValue: TResult): TResult;
lastOrDefault(defaultValue: TResult | null = null): TResult | null {
lastOrDefault(predicate: null, defaultValue: TResult): TResult;
lastOrDefault(predicate?: null, defaultValue: TResult | null = null): TResult | null {
return this._element;
}
}
29 changes: 29 additions & 0 deletions src/internal/partition.ts
@@ -0,0 +1,29 @@
export const partitionSymbol = Symbol();

export function isPartition<T>(source: Iterable<T>): source is IPartition<T> {
return typeof (source as any)[partitionSymbol] === 'function' &&
(source as any)[partitionSymbol]();
}

export interface IPartition<TElement> extends Iterable<TElement> {
[partitionSymbol](): boolean;

skip(count: number): Iterable<TElement>;

take(count: number): Iterable<TElement>;

elementAt(index: number): TElement;

elementAtOrDefault(index: number): TElement | null;
elementAtOrDefault(index: number, defaultValue: TElement): TElement;

first(): TElement;

firstOrDefault(): TElement | null;
firstOrDefault(predicate: null, defaultValue: TElement): TElement;

last(): TElement;

lastOrDefault(): TElement | null;
lastOrDefault(predicate: null, defaultValue: TElement): TElement;
}
4 changes: 2 additions & 2 deletions src/last.ts
@@ -1,4 +1,4 @@
import Partition from './internal/Partition';
import { isPartition } from './internal/partition';
import { noElements } from './internal/errors';

export default function last<TSource>(this: Iterable<TSource>, predicate?: (value: TSource) => boolean): TSource {
Expand All @@ -17,7 +17,7 @@ export default function last<TSource>(this: Iterable<TSource>, predicate?: (valu
return value as TSource;
}
} else {
if (this instanceof Partition) {
if (isPartition(this)) {
return (this as any).last();
}
if (Array.isArray(this)) {
Expand Down
6 changes: 3 additions & 3 deletions src/lastOrDefault.ts
@@ -1,4 +1,4 @@
import Partition from './internal/Partition';
import { isPartition } from './internal/partition';

export default function lastOrDefault<TSource>(this: Iterable<TSource>): TSource | null;
export default function lastOrDefault<TSource>(this: Iterable<TSource>, predicate: (value: TSource) => boolean): TSource | null;
Expand All @@ -19,8 +19,8 @@ export default function lastOrDefault<TSource>(this: Iterable<TSource>, predicat
return value as TSource;
}
} else {
if (this instanceof Partition) {
return (this as any).lastOrDefault(defaultValue);
if (isPartition(this)) {
return (this as any).lastOrDefault(null, defaultValue);
}
if (Array.isArray(this)) {
if ((this as any).length > 0) {
Expand Down

0 comments on commit b8558ae

Please sign in to comment.