RX JS Операторы для вложенных массивов - PullRequest
2 голосов
/ 25 февраля 2020

У меня есть вывод, как показано ниже из наблюдаемой. Я хочу преобразовать этот вывод в строковый формат как для всех истинных записей "John ~ Ford, Fiat" . Я хочу добиться этого с помощью операторов RX JS. Может кто-нибудь показать мне, как я могу добраться до этого.

[{
  "name":"John",
  "age":30,
  "selected" : true,
  "cars": [
      { "selected":"true",  "name":"Ford", "models": "Mustang"},
      { "selected":"false", "name":"BMW", "models": "320" },
      { "selected":"true", "name":"Fiat", "models":"500" }
  ]
 },
 {
  "name":"alex",
  "age":40,
  "selected" : false
  "cars": [
      { "selected":"true",  "name":"tesla", "models": "x"},
      { "selected":"false", "name":"merc", "models": "300" },
      { "selected":"true", "name":"honda", "models":"accord" }
   ]
  }
]

Я могу отфильтровать записи, но не уверен, как отформатировать строковый вывод ( "John ~ Ford, Fiat" .)

myComp.myService.carOptions$.pipe(
      take(1),
      flatMap(carOptions => carOptions as options[]),
      filter(carOption => carOption.selected === true),
      flatMap(options => options.values as values[]),
      filter(optionValue => optionValue.isSelected === true),
      toArray()
);

Ответы [ 2 ]

3 голосов
/ 25 февраля 2020

Это не проблема Rx JS, это проблема массива javascript.

Оператор filter Rx JS защищает канал и пропускает только те значения, которые соответствуют его критериям. Он не отфильтровывает элементы в пределах значений, которые поступают.

Фильтр take, который у вас есть в данный момент, пропустит только первое значение и не более. Возможно, вы не захотите хранить это там, но это не главная проблема здесь.

Вместо этого вы хотите взять то, что выходит из наблюдаемого, и преобразовать его в другое значение. Это делается внутри оператора RxJS map.

myComp.myService.carOptions$.pipe(
  map((result: any): string => {
    return result
      .filter(x => x.selected)
      .map(x => {
        const cars = x.cars
          .filter(x => x.selected)
          .map(x => x.name)
          .join(',');
        return `${x.name}~${cars}`;
      }).join('|');
  })
).subscribe(result => {      
  console.log(result);
});

Эта карта внутри функции преобразует массив в вашем вопросе в массив строк, соответствующих вашим критериям.

Сначала это только сохраняет выбранные объекты верхнего уровня. Затем он отображает каждый объект в строку. Эта строка представляет собой объединение «name» «~» и объединенного списка имен автомобилей, где значение «true» выбрано.

Я предположил, что car.selected должен быть логическим типом. Вам нужно будет изменить проверку, если это действительно строковый тип.

DEMO: https://stackblitz.com/edit/angular-snatak

1 голос
/ 25 февраля 2020

https://stackblitz.com/edit/angular-rxjs-filter-problem

  ngOnInit() {
    of(values)
      .pipe(
        map(items => items.filter(item => item.selected)),
        map(items =>
          items.map(item => {
            const cars = item.cars
              .filter(car => car.selected === "true")
              .map(car => car.name)
              .join(",");
            return item.name + "~" + cars;
          })
        )
      )
      .subscribe(val => {
        console.log(val);
        this.result = val;
        this.str = val.join(" | ");
      });
  }

Джон ~ Форд, Fiat | Alex ~ тесла, Хонда

...