Объединение подмассивов с использованием Observables

У меня есть эта структура данных:

[{
    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"
        }
    ]
}]

Я делаю следующий звонок в веб-сервис, чтобы получить предметы: this.dataService.get("items")

Вернулся Observable<Item[]>, Какие наблюдаемые операторы я могу использовать, чтобы получить только объединенный список подэлементов? Я хотел бы закончить что-то вроде этого:

[{
    id : 1,
    name : "SubItem 1"
}, {
    id : 2,
    name : "SubItem 2"
},
{
    id : 3,
    name : "SubItem 3"
}, {
    id : 4,
    name : "SubItem 4"
}]

Должен ли я использовать что-то вроде flatMap или же concat?

2 ответа

Решение

При условии, что это опечатка, а второй элемент имеет subItems как хорошо (а не searchProfiles), вам не нужен flatMap или что-либо в этом роде, вы можете сделать это на простой карте, используя операторы массива js:

var transformed = [].concat(...result.map(item => item.subItems));

или в вашем случае

httpResult$.map(result => [].concat(...result.map(item => item.subItems))

если использование разных ключей является преднамеренным, ваша внутренняя карта потребует немного больше логики, но отображение будет совершенно таким же

Вы хотите первым map() оператор, чтобы извлечь только те поля, которые вам нужны, и они сгладить массивы объектов с concatAll() (это небольшая хитрость с Observables более высокого порядка, см. Подписка на вложенную Observable для получения дополнительной информации):

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));

Это выводит на консоль:

{ id: 1, name: 'SubItem 1' }
{ id: 2, name: 'SubItem 2' }
{ id: 3, name: 'SubItem 3' }
{ id: 4, name: 'SubItem 4' }

В качестве альтернативы, если вы действительно хотите вывод в виде одного массива, вы можете добавить toArray() оператор между .concatAll() а также .subscribe(...) и вы получите:

[ { id: 1, name: 'SubItem 1' },
  { id: 2, name: 'SubItem 2' },
  { id: 3, name: 'SubItem 3' },
  { id: 4, name: 'SubItem 4' } ]
Другие вопросы по тегам