angular - 在传递过滤值的同时更新扫描累加器
我正在尝试使用scan来维护一个数据数组并进行一些过滤。
someObservable$.pipe(
filter(initial=> initial.length !== 0),
scan((acc, curr) => curr.filter(x => !acc.includes(x))),
map(data => etc...)
)
我想更新 acc 的值,使其以某种方式保持一个包含所有已处理数据的完整列表,但只将过滤后的值输出到 map。因此,如果第一个通过的列表是 [1,2,3],第二组是 [2,3,4],第一次处理时我希望 data 为 [1,2,3],同时 acc=[1,2,3],第二次处理时 data 为 [4],但 acc=[1,2,3,4]
我是在以一种笨拙的方式处理这件事吗?我感觉可能有更好的方法。
答案#1
我会在 scan 函数中使用 Set 类作为累加器
我查阅了 rxjs 文档寻找任何内置的替代方案,但找不到适合这种情况的。
请看看这个例子。
var subject = new rxjs.Subject();
const obs = subject.pipe(
rxjs.operators.scan((acc, current) => {current.map(pr => acc.add(pr)); return acc;}, new Set()) // 1 solution
//rxjs.operators.scan((acc, current) => [...new Set([...acc, ...current])]) // 2 solution
//rxjs.operators.scan((acc, current) => [...acc, ...current.filter(pr => !acc.includes(pr))]) // 3 solution - if you cant use Set
//rxjs.operators.scan((acc, current) => acc.concat(current.filter(pr => !acc.includes(pr)))) // 4 solution - if you cant use Set and spread
);
const subscription = obs.subscribe(val => {
console.log([...val]);
});
subject.next([1,2,3]);
subject.next([2,3,4]);<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>答案#2
如果我猜对了你的意图,下面的代码应该就足够了:
static acc = new Set<number>();
...
return someObservable$.pipe(
map( list => {
let res = [];
list.forEach( e => {
if ( !acc.has( e ) ) {
acc.set( e );
res.push( e );
}
} );
return res;
} ),
filter( list => list.length > 0 )
);
