【问题标题】:Filter an array of nested object - Observable过滤嵌套对象数组 - Observable
【发布时间】:2019-03-15 00:49:03
【问题描述】:

我有一个包含对象对象的数组的可观察对象。 (如图所示)。我有一个observableget 请求接收这些值,然后我有另一个observable 用于存储过滤值。我有一个 bindedinput 的 searchText 变量,每次输入更改时我都会调用一个函数。

 <input name="problem-search" [(ngModel)]="searchText" matInput placeholder="Search for problems..." (input)="filterProblems()">

到目前为止,我已经尝试过这个,但它没有产生所需的输出。它有时会过滤,但这是随机的,甚至与searchInput 无关。坦率地说,我什至不知道我是如何得到那个输出的。 Rxjs 有时可能会令人困惑。请让我知道我在这里做错了什么。

    filterProblems() {
    if (this.searchText === '') {
      this._filteredProblems$ = this._everyProblem$;
    }

    this._filteredProblems$ = this._everyProblem$.pipe(
      map(data => data),
      tap(ele => ele.filter(data => {
        Object.keys(data).forEach(key => {
          if (data[key].name.toLowerCase().includes(this.searchText)) {
            delete data[key];
          }
        });
      }))
    );

    this._filteredProblems$.subscribe(data => console.log(data))
  }

【问题讨论】:

  • 你想达到什么目的?目前,如果它与 searchText 匹配,则您正在删除它
  • @SachinGupta 根据 searchInput 过滤this._everyProblem$,并将结果分配给._filteredProblems$

标签: angular rxjs observable rxjs6


【解决方案1】:

tap operator 应该用于副作用,而不是流修改操作。以这种方式使用map operator 实际上并没有为您做任何事情。我认为您应该从 map 样式运算符之类的东西中返回过滤后的对象,以更改流返回的内容,而不是正在发出的原始对象。目前整个对象都被返回到流中,减去您从中删除的键。删除后,它们看起来就像从原始文件中删除了一样。

使用Object.keys 是一种能够迭代对象的方法,但在这种情况下,您可以使用Object.values 保存一个步骤,然后从该结果中提取您想要的键。

这样的东西应该接近你所需要的:

map((data: yourType[]) =>
  data.filter((item: yourType) =>
    (!this.searchText || !Object.values(item)[0].name.toLowerCase().includes(this.searchText))
),
  • 如果原始数据至少是一个空数组,那么从 data.filter 返回结果至少会给您一个空数组。
  • 对 searchText 的 flasy 值取反将返回所有项目
  • Object.values 将返回来自 guid 的对象列表
  • [0] 将返回第一个(应该只有一个)
  • 返回包含的倒数将保留不包含搜索文本的项目

或者,您可以设置触发流以观察源数据或输入是否发生变化。 - 将 searchText 放入 BehaviorSubject 中,以便您可以使用它来触发流中的更改。 - 将 searchText observable 和 _everyProblem$ observable 与 combineLatest 组合,并将结果设置为 _filteredProblems$ - 在里面应用一个类似的过滤器,以及去抖动

可能是这样的事情来激发一些想法:

this._filteredProblems$ = combineLatest(
  this.searchTextSubject.asObservable(),
  this._everyProblem$,
).pipe(
  debounce(() => timer(50))
  map((searchText: string, data: yourType[]) =>
    data.filter((item: yourType) =>
      (!searchText || !Object.values(item)[0].name.toLowerCase().includes(searchText))
  ),
);

【讨论】:

    猜你喜欢
    • 2020-01-16
    • 1970-01-01
    • 2020-03-11
    • 2020-03-08
    • 1970-01-01
    • 2022-12-03
    • 2020-09-17
    • 2019-10-15
    • 1970-01-01
    相关资源
    最近更新 更多