From 8ab0914cfdb184add54f9bf753669735c22a128a Mon Sep 17 00:00:00 2001 From: Jason Aden Date: Tue, 22 Aug 2017 15:08:09 -0400 Subject: [PATCH] feat(pluck): add higher-order lettable version of pluck --- src/operator/pluck.ts | 25 ++----------------- src/operators/index.ts | 1 + src/operators/pluck.ts | 54 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 src/operators/pluck.ts diff --git a/src/operator/pluck.ts b/src/operator/pluck.ts index dc7cc18173..57d2bb26be 100644 --- a/src/operator/pluck.ts +++ b/src/operator/pluck.ts @@ -1,5 +1,5 @@ import { Observable } from '../Observable'; -import { map } from './map'; +import { pluck as higherOrder } from '../operators/pluck'; /** * Maps each source value (an object) to its specified nested property. @@ -28,26 +28,5 @@ import { map } from './map'; * @owner Observable */ export function pluck(this: Observable, ...properties: string[]): Observable { - const length = properties.length; - if (length === 0) { - throw new Error('list of properties cannot be empty.'); - } - return map.call(this, plucker(properties, length)); -} - -function plucker(props: string[], length: number): (x: string) => any { - const mapper = (x: string) => { - let currentProp = x; - for (let i = 0; i < length; i++) { - const p = currentProp[props[i]]; - if (typeof p !== 'undefined') { - currentProp = p; - } else { - return undefined; - } - } - return currentProp; - }; - - return mapper; + return higherOrder(...properties)(this); } diff --git a/src/operators/index.ts b/src/operators/index.ts index baa5444a42..1675425138 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -48,6 +48,7 @@ export { observeOn } from './observeOn'; export { onErrorResumeNext } from './onErrorResumeNext'; export { pairwise } from './pairwise'; export { partition } from './partition'; +export { pluck } from './pluck'; export { publish } from './publish'; export { race } from './race'; export { reduce } from './reduce'; diff --git a/src/operators/pluck.ts b/src/operators/pluck.ts new file mode 100644 index 0000000000..404ff1dfcd --- /dev/null +++ b/src/operators/pluck.ts @@ -0,0 +1,54 @@ +import { Observable } from '../Observable'; +import { map } from './map'; +import { OperatorFunction } from '../interfaces'; + +/** + * Maps each source value (an object) to its specified nested property. + * + * Like {@link map}, but meant only for picking one of + * the nested properties of every emitted object. + * + * + * + * Given a list of strings describing a path to an object property, retrieves + * the value of a specified nested property from all values in the source + * Observable. If a property can't be resolved, it will return `undefined` for + * that value. + * + * @example Map every click to the tagName of the clicked target element + * var clicks = Rx.Observable.fromEvent(document, 'click'); + * var tagNames = clicks.pluck('target', 'tagName'); + * tagNames.subscribe(x => console.log(x)); + * + * @see {@link map} + * + * @param {...string} properties The nested properties to pluck from each source + * value (an object). + * @return {Observable} A new Observable of property values from the source values. + * @method pluck + * @owner Observable + */ +export function pluck(...properties: string[]): OperatorFunction { + const length = properties.length; + if (length === 0) { + throw new Error('list of properties cannot be empty.'); + } + return (source: Observable) => map(plucker(properties, length))(source as any); +} + +function plucker(props: string[], length: number): (x: string) => any { + const mapper = (x: string) => { + let currentProp = x; + for (let i = 0; i < length; i++) { + const p = currentProp[props[i]]; + if (typeof p !== 'undefined') { + currentProp = p; + } else { + return undefined; + } + } + return currentProp; + }; + + return mapper; +}