Skip to content
This repository has been archived by the owner on Apr 20, 2018. It is now read-only.

Commit

Permalink
Merge pull request #526 from sergi/deep_pluck
Browse files Browse the repository at this point in the history
Implement `deepPluck`, a pluck operator for nested properties
  • Loading branch information
mattpodwysocki committed Feb 5, 2015
2 parents 8998098 + c9885f7 commit 8364c13
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 7 deletions.
35 changes: 32 additions & 3 deletions doc/api/core/operators/pluck.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
### `Rx.Observable.prototype.pluck(property)`
[Ⓢ](https://github.com/Reactive-Extensions/RxJS/blob/master/src/core/linq/observable/pluck.js "View in source")
[Ⓢ](https://github.com/Reactive-Extensions/RxJS/blob/master/src/core/linq/observable/pluck.js#L10 "View in source")

Projects each element of an observable sequence into a new form by incorporating the element's index.
Returns an Observable containing the value of a specified nested property from
all elements in the Observable sequence. If a property can't be resolved, it
will return `undefined` for that value.

#### Arguments
1. `property` *(`String`)*: The property to pluck.
1. `property` *(`String`)*: The property or properties to pluck. `pluck`
accepts an unlimited number of nested property parameters.

#### Returns
*(`Observable`)*: Returns a new Observable sequence of property values.
Expand Down Expand Up @@ -34,6 +37,32 @@ var subscription = source.subscribe(
// => Next: 1
// => Next: 2
// => Completed

// Using nested properties:

var source = Rx.Observable
.from([
{ valueA: { valueB: { valueC: 0 }}},
{ valueA: { valueB: { valueC: 1 }}},
{ valueA: { valueB: 2 }},
])
.pluck('valueA', 'valueB', 'valueC');

var subscription = source.subscribe(
function (x) {
console.log('Next: ' + x);
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});

// => Next: 0
// => Next: 1
// => Next: undefined
// => Completed
```

### Location
Expand Down
26 changes: 22 additions & 4 deletions src/core/linq/observable/pluck.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
/**
* Retrieves the value of a specified property from all elements in the Observable sequence.
* @param {String} prop The property to pluck.
* Retrieves the value of a specified nested property from all elements in
* the Observable sequence.
* @param {String} nestedProps The nested property to pluck.
* @returns {Observable} Returns a new Observable sequence of property values.
*/
observableProto.pluck = function (prop) {
return this.map(function (x) { return x[prop]; });
observableProto.pluck = function () {
var args = [].slice.call(arguments);
var len = args.length;
return this.map(function (x) {
if (len === 0) {
return undefined;
}

var currentProp = x;
for (var i = 0; i < len; i++) {
var p = currentProp[args[i]];
if (typeof p !== 'undefined') {
currentProp = p;
} else {
return undefined;
}
}
return currentProp;
});
};
60 changes: 60 additions & 0 deletions tests/observable/pluck.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,63 @@ test('Pluck_Completed', function () {

xs.subscriptions.assertEqual(subscribe(200, 400));
});

test('Deep_Pluck_Nested_Completed', function () {
var scheduler = new TestScheduler();

var xs = scheduler.createHotObservable(
onNext(180, {a: {b: {c: 1}}}),
onNext(210, {a: {b: {c: 2}}}),
onNext(240, {a: {b: {c: 3}}}),
onNext(290, {a: {b: {c: 4}}}),
onNext(350, {a: {b: {c: 5}}}),
onCompleted(400),
onNext(410, {a: {b: {c: -1}}}),
onCompleted(420),
onError(430, new Error('ex'))
);

var results = scheduler.startWithCreate(function () {
return xs.pluck('a', 'b', 'c');
});

results.messages.assertEqual(
onNext(210, 2),
onNext(240, 3),
onNext(290, 4),
onNext(350, 5),
onCompleted(400)
);

xs.subscriptions.assertEqual(subscribe(200, 400));
});

test('Deep_Pluck_Nested_Edgecases', function () {
var scheduler = new TestScheduler();

var xs = scheduler.createHotObservable(
onNext(180, {a: {b: {c: 1}}}),
onNext(210, {a: {b: 2}}),
onNext(240, {a: {c: {c: 3}}}),
onNext(290, {}),
onNext(350, {a: {b: {c: 5}}}),
onCompleted(400),
onNext(410, {a: {b: {c: -1}}}),
onCompleted(420),
onError(430, new Error('ex'))
);

var results = scheduler.startWithCreate(function () {
return xs.pluck('a', 'b', 'c');
});

results.messages.assertEqual(
onNext(210, undefined),
onNext(240, undefined),
onNext(290, undefined),
onNext(350, 5),
onCompleted(400)
);

xs.subscriptions.assertEqual(subscribe(200, 400));
});

0 comments on commit 8364c13

Please sign in to comment.