I have this data structure:
[{
id : 1,
name : "Item 1",
subItems : [{
id : 1,
name : "SubItem 1"
},{
id : 2,
name : "SubItem 2"
}
]
}, {
id : 2,
name : "Item 2",
subItems : [{
id : 3,
name : "SubItem 3"
}, {
id : 4,
name : "SubItem 4"
}
]
}]
I make the following call to a web service to get the items:
this.dataService.get("items")
Returned is an Observable<Item[]>
. What Observable operators can I use to only get a concatenated list of SubItems? I would like to end up with something like this:
[{
id : 1,
name : "SubItem 1"
}, {
id : 2,
name : "SubItem 2"
},
{
id : 3,
name : "SubItem 3"
}, {
id : 4,
name : "SubItem 4"
}]
Should I use something like flatMap
or concat
?
Provided it is a typo and the second element has subItems
as well (and not searchProfiles
), you don't need flatMap or any thing of the sort, you can do it in a plain map using js array operators:
var transformed = [].concat(...result.map(item => item.subItems));
or in your case
httpResult$.map(result => [].concat(...result.map(item => item.subItems))
if the use of different keys is deliberate, your internal map will require a bit more logic but the mapping will be quite the same
You want to first map()
operator to extract only fields you need and them flatten the arrays of objects with concatAll()
(it's a little trick with higher order Observables, see Subscribing to a nested Observable for more info):
var data = [{
id : 1,
name : "Item 1",
subItems : [
{ id : 1, name : "SubItem 1" },
{ id : 2, name : "SubItem 2" }
]
}, {
id : 2,
name : "Item 2",
searchProfiles : [
{ id : 3, name : "SubItem 3" },
{ id : 4, name : "SubItem 4" }
]
}];
Observable.from(data)
.map(item => {
if (item.searchProfiles) {
return item.searchProfiles;
} else if (item.subItems) {
return item.subItems
}
})
.concatAll()
.subscribe(val => console.log(val));
This prints to console:
{ id: 1, name: 'SubItem 1' }
{ id: 2, name: 'SubItem 2' }
{ id: 3, name: 'SubItem 3' }
{ id: 4, name: 'SubItem 4' }
Alternatively, if you really want the output as a single array then you can add toArray()
operator between .concatAll()
and .subscribe(...)
and you'll receive:
[ { id: 1, name: 'SubItem 1' },
{ id: 2, name: 'SubItem 2' },
{ id: 3, name: 'SubItem 3' },
{ id: 4, name: 'SubItem 4' } ]