首页 > 解决方案 > RxJS 6 过滤和映射可观察的项目数组

问题描述

在我使用 RxJS 6.3.3 的 Angular 7.1.1 应用程序中,应将可观察的计划数组转换为可观察的活动计划卡数组。有源滤波器是:

filter(plan => plan.is_active)

计划到卡片的转化为:

map(plan => new PlanCard(plan, 1, 1))

所以,据推测,答案是这样的:

plans: Observable<Plan[]> = getPlans();

cards: Observable<PlanCard[]> = plans.pipe(
  mergeAll(),
  filter(plan => plan.is_active),
  map(plan => new PlanCard(plan, 1, 1)),
  toArray()
);

但很可惜,cards是空的。

计划可以通过以下方式正确转换为卡片:

cards: Observable<PlanCard[]> = plans.pipe(
  map(plans => plans.map(plan => new PlanCard(plan, 1, 1)))
);

但不幸的是,添加过滤器不会过滤计划:

cards: Observable<PlanCard[]> = plans.pipe(
  filter(plans => plans.filter(plan => plan.is_active)),
  map(plans => plans.map(plan => new PlanCard(plan, 1, 1)))
);

有更好的想法吗?

export const planData: Plan[] = [{
  name: 'P1',
  is_active: true
}, {
  name: 'P2',
  is_active: true
}, {
  name: 'P3',
  is_active: true
}, {
  name: 'P4',
  is_active: true
}, {
  name: 'P5',
  is_active: false
}];

export const plans = createObservable(planData);

标签: angularrxjs

解决方案


mergeAll 合并一个 observable 的 observable。

你要

cards: Observable<PlanCard[]> = plans.pipe(
  map(plans => plans.filter(plan => plan.is_active)), // An array comes down the pipe, you don't want to filter out the arrays but the elements in the array
  map(plans => plans.map(plan => new PlanCard(plan, 1, 1))), // An array of active plans can be mapped into an array of PlanCards
  reduce((results, plans) => [...results, ...plans], []) // Reduce all the arrays into a single array
);

如果您希望每次新阵列下降时减少的累加器从管道下降,您可以使用扫描而不是减少,只有在所有阵列都下降到管道后才会触发。

我通常不使用过滤器后跟地图,但更容易看到发生了什么,我通常会在一个步骤中使用减少,

plans => plans.reduce((results, plan) => plan.is_active ? [...results, new PlanCard(plan, 1, 1)] : results, [])

与过滤器后跟映射相同,但在一次迭代中而不是两次迭代中完成。

当您拥有数组的可观察对象时,这可能会非常令人困惑,您需要考虑要将哪些函数应用于可观察对象以及要将哪些函数应用于管道中的数组。

const { from } = rxjs;
const { map, reduce } = rxjs.operators;

const plans = from([
  [{id: 1, is_active: true}, {id: 2, is_active: false}, {id: 3, is_active: true}, {id: 4, is_active: true}],
  [{id: 5, is_active: true}, {id: 6, is_active: true}],
  [{id: 7, is_active: false}, {id: 8, is_active: true}, {id: 9, is_active: true}],
  [{id: 10, is_active: true}, {id: 11, is_active: false}, {id: 12, is_active: true}, {id: 13, is_active: false}],
]);

function PlanCard(plan) {
  this.id = plan.id;
}

plans.pipe(
  map(plans => plans.reduce((results, plan) => plan.is_active ? [...results, new PlanCard(plan, 1, 1)] : results, [])),
  reduce((results, plans) => [...results, ...plans], [])
).subscribe(results => { console.log(results); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.min.js"></script>


推荐阅读