Skip to content

Commit

Permalink
feat(partition): partition static function. partition operator is dep…
Browse files Browse the repository at this point in the history
…recated (#4419) (#4685)
  • Loading branch information
dkosasih authored and benlesh committed Apr 23, 2019
1 parent b5a2ac9 commit d5d6980
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 56 deletions.
13 changes: 9 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions spec-dtslint/observables/partition-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { of, partition } from 'rxjs';

it('should infer correctly', () => {
const o = partition(of('a', 'b', 'c'), (value, index) => true); // $ExpectType [Observable<string>, Observable<string>]
const p = partition(of('a', 'b', 'c'), () => true); // $ExpectType [Observable<string>, Observable<string>]
});

it('should accept a thisArg parameter', () => {
const o = partition(of('a', 'b', 'c'), () => true, 5); // $ExpectType [Observable<string>, Observable<string>]
});

it('should enforce predicate', () => {
const o = partition(of('a', 'b', 'c')); // $ExpectError
});

it('should enforce predicate types', () => {
const o = partition(of('a', 'b', 'c'), 'nope'); // $ExpectError
const p = partition(of('a', 'b', 'c'), (value: number) => true); // $ExpectError
const q = partition(of('a', 'b', 'c'), (value, index: string) => true); // $ExpectError
});
24 changes: 0 additions & 24 deletions spec-dtslint/operators/partition-spec.ts.disabled

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { expect } from 'chai';
import * as Rx from 'rxjs/Rx';
import { Observable, partition, of } from 'rxjs';
import { map, mergeMap } from 'rxjs/operators';
import { hot, cold, expectObservable, expectSubscriptions } from '../helpers/marble-testing';

// TODO: The imports on these tests can't be modernized until we do away with
// the partition "operator" and make it a creation method.
declare function asDiagram(arg: string): Function;

const Observable = Rx.Observable;

/** @test {partition} */
describe('Observable.prototype.partition', () => {
function expectObservableArray(result: Rx.Observable<string>[], expected: string[]) {
function expectObservableArray(result: Observable<string>[], expected: string[]) {
for (let idx = 0; idx < result.length; idx++ ) {
expectObservable(result[idx]).toBe(expected[idx]);
}
Expand All @@ -23,7 +20,7 @@ describe('Observable.prototype.partition', () => {
const expected = ['--1-----3---------5------|',
'----2----------4------6--|'];

const result = e1.partition((x: any) => x % 2 === 1);
const result = partition(e1, (x: any) => x % 2 === 1);

expectObservableArray(result, expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
Expand All @@ -39,7 +36,7 @@ describe('Observable.prototype.partition', () => {
return x === 'a';
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -53,7 +50,7 @@ describe('Observable.prototype.partition', () => {
return index % 2 === 0;
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -67,7 +64,7 @@ describe('Observable.prototype.partition', () => {
return x === this.value;
}

expectObservableArray(e1.partition(predicate, {value: 'a'}), expected);
expectObservableArray(partition(e1, predicate, {value: 'a'}), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -81,7 +78,7 @@ describe('Observable.prototype.partition', () => {
return x === 'a';
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -95,7 +92,7 @@ describe('Observable.prototype.partition', () => {
return x === 'a';
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -115,7 +112,7 @@ describe('Observable.prototype.partition', () => {
return match;
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -129,7 +126,7 @@ describe('Observable.prototype.partition', () => {
return x === 'x';
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -143,7 +140,7 @@ describe('Observable.prototype.partition', () => {
return x === 'x';
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -157,7 +154,7 @@ describe('Observable.prototype.partition', () => {
return x === 'a';
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -171,7 +168,7 @@ describe('Observable.prototype.partition', () => {
return x === 'a';
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -185,7 +182,7 @@ describe('Observable.prototype.partition', () => {
return x === 'a';
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -199,7 +196,7 @@ describe('Observable.prototype.partition', () => {
return x === 'a';
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -213,7 +210,7 @@ describe('Observable.prototype.partition', () => {
return x === 'a';
}

expectObservableArray(e1.partition(predicate), expected);
expectObservableArray(partition(e1, predicate), expected);
expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);
});

Expand All @@ -227,7 +224,7 @@ describe('Observable.prototype.partition', () => {
function predicate(x: string) {
return x === 'a';
}
const result = e1.partition(predicate);
const result = partition(e1, predicate);

for (let idx = 0; idx < result.length; idx++ ) {
expectObservable(result[idx], unsub).toBe(expected[idx]);
Expand All @@ -242,11 +239,10 @@ describe('Observable.prototype.partition', () => {
'----b--- '];
const unsub = ' ! ';

const result = e1
.mergeMap((x: string) => Observable.of(x))
.partition((x: string) => x === 'a')
.map((observable: Rx.Observable<string>) =>
observable.mergeMap((x: string) => Observable.of(x)));
const e1Pipe = e1.pipe(
mergeMap((x: string) => of(x))
);
const result = partition(e1Pipe, (x: string) => x === 'a');

expectObservable(result[0], unsub).toBe(expected[0]);
expectObservable(result[1], unsub).toBe(expected[1]);
Expand All @@ -256,10 +252,10 @@ describe('Observable.prototype.partition', () => {
it('should accept thisArg', () => {
const thisArg = {};

Observable.of(1).partition(function (this: any, value: number) {
partition(of(1), function (this: any, value: number) {
expect(this).to.deep.equal(thisArg);
return true;
}, thisArg)
.forEach((observable: Rx.Observable<number>) => observable.subscribe());
.forEach((observable: Observable<number>) => observable.subscribe());
});
});
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export { never } from './internal/observable/never';
export { of } from './internal/observable/of';
export { onErrorResumeNext } from './internal/observable/onErrorResumeNext';
export { pairs } from './internal/observable/pairs';
export { partition } from './internal/observable/partition';
export { race } from './internal/observable/race';
export { range } from './internal/observable/range';
export { throwError } from './internal/observable/throwError';
Expand Down
67 changes: 67 additions & 0 deletions src/internal/observable/partition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { not } from '../util/not';
import { subscribeTo } from '../util/subscribeTo';
import { filter } from '../operators/filter';
import { ObservableInput } from '../types';
import { Observable } from '../Observable';

/**
* Splits the source Observable into two, one with values that satisfy a
* predicate, and another with values that don't satisfy the predicate.
*
* <span class="informal">It's like {@link filter}, but returns two Observables:
* one like the output of {@link filter}, and the other with values that did not
* pass the condition.</span>
*
* ![](partition.png)
*
* `partition` outputs an array with two Observables that partition the values
* from the source Observable through the given `predicate` function. The first
* Observable in that array emits source values for which the predicate argument
* returns true. The second Observable emits source values for which the
* predicate returns false. The first behaves like {@link filter} and the second
* behaves like {@link filter} with the predicate negated.
*
* ## Example
* Partition a set of numbers into odds and evens observables
* ```ts
* import { of, partition } from 'rxjs';
*
* const observableValues = of(1, 2, 3, 4, 5, 6);
* const [evens$, odds$] = partition(observableValues, (value, index) => value % 2 === 0);
*
* odds$.subscribe(x => console.log('odds', x));
* evens$.subscribe(x => console.log('evens', x));
*
* // Logs:
* // odds 1
* // odds 3
* // odds 5
* // evens 2
* // evens 4
* // evens 6
* ```
*
* @see {@link filter}
*
* @param {function(value: T, index: number): boolean} predicate A function that
* evaluates each value emitted by the source Observable. If it returns `true`,
* the value is emitted on the first Observable in the returned array, if
* `false` the value is emitted on the second Observable in the array. The
* `index` parameter is the number `i` for the i-th source emission that has
* happened since the subscription, starting from the number `0`.
* @param {any} [thisArg] An optional argument to determine the value of `this`
* in the `predicate` function.
* @return {[Observable<T>, Observable<T>]} An array with two Observables: one
* with values that passed the predicate, and another with values that did not
* pass the predicate.
*/
export function partition<T>(
source: ObservableInput<T>,
predicate: (value: T, index: number) => boolean,
thisArg?: any
): [Observable<T>, Observable<T>] {
return [
filter(predicate, thisArg)(new Observable<T>(subscribeTo(source))),
filter(not(predicate, thisArg) as any)(new Observable<T>(subscribeTo(source)))
] as [Observable<T>, Observable<T>];
}
3 changes: 3 additions & 0 deletions src/internal/operators/partition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ import { UnaryFunction } from '../types';
* @method partition
* @owner Observable
*/
/**
* @deprecated use `partition` static creation function instead
*/
export function partition<T>(predicate: (value: T, index: number) => boolean,
thisArg?: any): UnaryFunction<Observable<T>, [Observable<T>, Observable<T>]> {
return (source: Observable<T>) => [
Expand Down

0 comments on commit d5d6980

Please sign in to comment.