简体   繁体   English

RxJS 6 过滤并映射可观察的项目数组

[英]RxJS 6 filter and map an observable array of items

In my Angular 7.1.1 application with RxJS 6.3.3, an observable array of plans should be transformed into an observable array of active plan cards.在我的带有 RxJS 6.3.3 的 Angular 7.1.1 应用程序中,一个可观察的计划数组应该转换为一个可观察的活动计划卡片数组。 The active filter is:有源滤波器是:

filter(plan => plan.is_active)

and the transformation of plan to card is: plan 到 card 的转换是:

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

so, presumable, the answer is something like:所以,可以推测,答案是这样的:

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

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

But alas, cards is empty.但是,唉, cards是空的。

The plans can correctly be transformed to cards via:计划可以通过以下方式正确转换为卡片:

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

but adding a filter prior does not filter the plans, unfortunately:但不幸的是,先添加过滤器并不能过滤计划:

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

Any better ideas?有更好的主意吗?

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

mergeAll merges an observable of observables. mergeAll 合并一个 observable of observables。

You want你要

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

You can use scan instead of reduce if you want the accumulator of the reduce to come down the pipe each time a new array comes down, reduce only fires after all arrays have come down the pipe.如果您希望 reduce 的累加器在每次新阵列下降时从管道下降,则可以使用扫描而不是 reduce,只有在所有阵列下降到管道后才减少触发。

I don't usually use a filter followed by a map but it is easier to see what is going on, I would usually do it in a single step with a reduce,我通常不使用过滤器后跟地图,但更容易看到发生了什么,我通常会在一个步骤中使用 reduce,

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

Is the same as a filter followed by a map but does it in a single iteration instead of two.与过滤器后跟地图相同,但它是在一次迭代中而不是两次迭代中完成的。

It can be quite confusing when you have observables of arrays, you need to consider what functions you want to apply to the observable and which you want to apply to the array that comes down the pipe.当您有数组的可观察对象时,这可能会非常混乱,您需要考虑要将哪些函数应用于可观察对象以及要将哪些函数应用于管道中的数组。

 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>

This had me scratching my head for a while, so a brief example which may be of help if you're looking to filter an observable array of objects.这让我摸不着头脑了一会儿,所以如果你想过滤一个可观察的对象数组,那么一个简短的例子可能会有所帮助。 Kudos to @ Adrian for pointing me in the right direction.感谢@Adrian为我指明了正确的方向。

If you have a service that returns an observable array of objects, eg:如果您有一个返回可观察对象数组的服务,例如:

dataSub = new BehaviorSubject<Array<object>>([]);

getItems(): Observable<Array<object>>  {
    return this.dataSub.asObservable();
}

You can filter with a given criteria with the following.您可以使用以下给定条件进行过滤。 In this example, I want only elements where the property 'selected' is true.在此示例中,我只需要属性“selected”为 true 的元素。

constructor() {
  this.getItems()
    .pipe(
      map(items => items), /* Don't forget to add this! */
      filter(item => item['selected'] === true)
    )
    .subscribe(data => {
      console.log(data);
    });
}

The (rookie) error which led to my confusion was omitting the 'map', so the filter function was being applied to the whole array, rather than each element.导致我困惑的(菜鸟)错误是省略了“地图”,因此过滤器功能被应用于整个数组,而不是每个元素。

RXJS 更好的方法来 map 和过滤器数组内部的 Observable<object><div id="text_translate"><p> 这是我想要完成的一个非常简单的版本。 目前它正在按预期工作,但我只是想知道是否有更短/更清洁的方法来实现 pipe() 内部的运算符</p><p><strong>当前行为:</strong>在包含数组“项目”的属性的可观察对象上调用 pipe。 在 pipe 内部,过滤、排序然后将项目发布到行为主体。</p><pre> public items$: BehaviorSubject public testObservable = () =&gt; of({ Test: '123', Properties: 'props', Items: [ { key: 1, val: 'test1' }, { key: 2, val: 'test2' }, { key: 3, val: 'test3' } ] }); testMethod() { this.testObservable().pipe( pluck('Items'), map(items =&gt; items.filter(item =&gt; item.key,= 2)). map(items =&gt; items,sort((a. b) =&gt; (a.key &gt; b?key: 1, -1))). tap(items =&gt; { this.items$;next(items) }) );</pre></div></object> - RXJS better way to map and filter array inside of Observable<object>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 RxJs如何在Observable中映射项目<Array> - RxJs how to map the items in an Observable<Array> Angular RXJS 6:过滤与 object 键匹配的项目的可观察数组 - Angular RXJS 6: filter observable array for items matching object key RXJS 更好的方法来 map 和过滤器数组内部的 Observable<object><div id="text_translate"><p> 这是我想要完成的一个非常简单的版本。 目前它正在按预期工作,但我只是想知道是否有更短/更清洁的方法来实现 pipe() 内部的运算符</p><p><strong>当前行为:</strong>在包含数组“项目”的属性的可观察对象上调用 pipe。 在 pipe 内部,过滤、排序然后将项目发布到行为主体。</p><pre> public items$: BehaviorSubject public testObservable = () =&gt; of({ Test: '123', Properties: 'props', Items: [ { key: 1, val: 'test1' }, { key: 2, val: 'test2' }, { key: 3, val: 'test3' } ] }); testMethod() { this.testObservable().pipe( pluck('Items'), map(items =&gt; items.filter(item =&gt; item.key,= 2)). map(items =&gt; items,sort((a. b) =&gt; (a.key &gt; b?key: 1, -1))). tap(items =&gt; { this.items$;next(items) }) );</pre></div></object> - RXJS better way to map and filter array inside of Observable<object> 使用 RxJS 更新 Observable 数组中的项目 - Update Items in Observable Array with RxJS rxjs过滤可观察对象的数组 - rxjs Filter an array of objects observable Rxjs 滤波器可通过滤波器阵列观察 - Rxjs filter observable with array of filters 对RXJS Observable数组进行简单过滤 - Simple filter on array of RXJS Observable RxJs:具有内部可观察值的过滤器数组 - RxJs: Filter array with inner observable rxjs6过滤器可观察 <Array<any> &gt; - rxjs6 filter Observable<Array<any>> 如何使用rxjs 6通过异步过滤数组的Observable - How to filter Observable of array with rxjs 6 with async
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM