RxJs 唯一地合并两个 observables
RxJs merging two observables uniquely
我正在使用 rxjs 在 angular 应用程序中构建搜索和过滤系统。
我有以下内容:
interface User{ //exmaple model
_id: string;
name: string;
}
filters$ = new BehaviorSubject<Array<User>>([]);
search$ = new BehaviorSubject<Array<User>>([]);
// I use these two and merge them in another function as following
const myData$ = merge(this.search$.asObservable(), this.filters$.asObservable())
.pipe(distinctUntilChanged(distinctCheck))
效用函数 distinctCheck
类似于:
const distinctKey = (elem) => {
if(elem === null){
return elem
}
if(this.hasId(elem)){
return elem["_id"];
}
if(this.hasName(elem)){
return elem["name"]
}
return this.createComparisonString(elem)
}
但这使我无法观察到一个或另一个。所以我的问题是:
如何合并两个可观察对象并仅发出两个数组共有的值?有时 filters$ 可能会发出一个包含 30 个元素的数组。有时 search$ 可能会发出只有 2 个元素的数组?
I.E:
如果 filter$
包含:
[{_id:'1', name:'jhon'},{_id:'2', name:'doe'},{_id:'3', name:'jolly'},{_id:'4', name:'some random dude'},{_id:'5', name:'some random other dude'},{_id:'6', name:'johny'},{_id:'7', name:'bravo'}]
和search$
包含:
[{_id:'1', name:'jhon'},{_id:'101', name:'myDoe'},{_id:'301', name:'some-jolly'},{_id:'4', name:'some random dude'}, {_id:'7', name:'bravo'}]
我想 myData$
发出类似的东西:
[{_id:'1', name:'jhon'},{_id:'4', name:'some random dude'}, {_id:'7', name:'bravo'}]
谢谢大家! :)
像这样的东西应该可以工作:
const filters$ = new BehaviorSubject<Array<{ id: string }>>([]);
const search$ = new BehaviorSubject<Array<{ id: string }>>([]);
const combinedAndFiltered$ = combineLatest(filters$, search$)
.pipe(map(([filters, searches]) => {
return filters.filter(filter => !!searches.find(search => search.id === filter.id));
}));
combinedAndFiltered$.subscribe(console.log)
distinctUntilChanged
运算符的compare
函数用于判断上一次发射是否与当前发射不同。
据我了解您的问题,您正在寻找 search
和 filter
数组之间的交集。
首先,使用 combineLatest
运算符在 filter$
的 search$
发出时得到通知。
然后,您可以使用类似 lodash 的 intersectionWith
来获取数组交集。
您的代码应如下所示:
const comperator = (search, filter) => filter._id === search._id && filter.name === search.name;
const myData$ = combineLatest(search$, filter$).pipe(
map(([search, filter]) => intersectionWith(search, filter, comperator))
);
您可以在 this stackblitz
中查看完整的 运行 代码
你实际上可以用简单的 Javascript 来实现它。
var filterArr = [{_id:'1', name:'jhon'},{_id:'2', name:'doe'},{_id:'3', name:'jolly'},{_id:'4', name:'some random dude'},{_id:'5', name:'some random other dude'},{_id:'6', name:'johny'},{_id:'7', name:'bravo'}]
var searchArr = [{_id:'1', name:'jhon'},{_id:'101', name:'myDoe'},{_id:'301', name:'some-jolly'},{_id:'4', name:'some random dude'}, {_id:'7', name:'bravo'}]
var data = filterArr.filter(userFilter => searchArr.some(userSearch => userFilter._id == userSearch._id))
console.log(data);
至于可观测值,您可以尝试使用 combineLatest
方法将它们组合起来。
const myData$ = combineLatest(this.search$.asObservable(), this.filters$.asObservable()).pipe(
map(([filterArr, searcheArr]) => filterArr.filter(userFilter => searchArr.some(userSearch => userFilter._id == userSearch._id)))
)
我正在使用 rxjs 在 angular 应用程序中构建搜索和过滤系统。
我有以下内容:
interface User{ //exmaple model
_id: string;
name: string;
}
filters$ = new BehaviorSubject<Array<User>>([]);
search$ = new BehaviorSubject<Array<User>>([]);
// I use these two and merge them in another function as following
const myData$ = merge(this.search$.asObservable(), this.filters$.asObservable())
.pipe(distinctUntilChanged(distinctCheck))
效用函数 distinctCheck
类似于:
const distinctKey = (elem) => {
if(elem === null){
return elem
}
if(this.hasId(elem)){
return elem["_id"];
}
if(this.hasName(elem)){
return elem["name"]
}
return this.createComparisonString(elem)
}
但这使我无法观察到一个或另一个。所以我的问题是:
如何合并两个可观察对象并仅发出两个数组共有的值?有时 filters$ 可能会发出一个包含 30 个元素的数组。有时 search$ 可能会发出只有 2 个元素的数组?
I.E:
如果 filter$
包含:
[{_id:'1', name:'jhon'},{_id:'2', name:'doe'},{_id:'3', name:'jolly'},{_id:'4', name:'some random dude'},{_id:'5', name:'some random other dude'},{_id:'6', name:'johny'},{_id:'7', name:'bravo'}]
和search$
包含:
[{_id:'1', name:'jhon'},{_id:'101', name:'myDoe'},{_id:'301', name:'some-jolly'},{_id:'4', name:'some random dude'}, {_id:'7', name:'bravo'}]
我想 myData$
发出类似的东西:
[{_id:'1', name:'jhon'},{_id:'4', name:'some random dude'}, {_id:'7', name:'bravo'}]
谢谢大家! :)
像这样的东西应该可以工作:
const filters$ = new BehaviorSubject<Array<{ id: string }>>([]);
const search$ = new BehaviorSubject<Array<{ id: string }>>([]);
const combinedAndFiltered$ = combineLatest(filters$, search$)
.pipe(map(([filters, searches]) => {
return filters.filter(filter => !!searches.find(search => search.id === filter.id));
}));
combinedAndFiltered$.subscribe(console.log)
distinctUntilChanged
运算符的compare
函数用于判断上一次发射是否与当前发射不同。
据我了解您的问题,您正在寻找 search
和 filter
数组之间的交集。
首先,使用 combineLatest
运算符在 filter$
的 search$
发出时得到通知。
然后,您可以使用类似 lodash 的 intersectionWith
来获取数组交集。
您的代码应如下所示:
const comperator = (search, filter) => filter._id === search._id && filter.name === search.name;
const myData$ = combineLatest(search$, filter$).pipe(
map(([search, filter]) => intersectionWith(search, filter, comperator))
);
您可以在 this stackblitz
中查看完整的 运行 代码你实际上可以用简单的 Javascript 来实现它。
var filterArr = [{_id:'1', name:'jhon'},{_id:'2', name:'doe'},{_id:'3', name:'jolly'},{_id:'4', name:'some random dude'},{_id:'5', name:'some random other dude'},{_id:'6', name:'johny'},{_id:'7', name:'bravo'}]
var searchArr = [{_id:'1', name:'jhon'},{_id:'101', name:'myDoe'},{_id:'301', name:'some-jolly'},{_id:'4', name:'some random dude'}, {_id:'7', name:'bravo'}]
var data = filterArr.filter(userFilter => searchArr.some(userSearch => userFilter._id == userSearch._id))
console.log(data);
至于可观测值,您可以尝试使用 combineLatest
方法将它们组合起来。
const myData$ = combineLatest(this.search$.asObservable(), this.filters$.asObservable()).pipe(
map(([filterArr, searcheArr]) => filterArr.filter(userFilter => searchArr.some(userSearch => userFilter._id == userSearch._id)))
)