【问题标题】:How to filter observable array?如何过滤可观察数组?
【发布时间】:2018-07-24 14:29:11
【问题描述】:

我有以下可观察的数组:

const stages = [
{Id: 1, Name: "First stage", RoleId: 71},
{Id: 2, Name: "Second stage", RoleId: 72},
{Id: 3, Name: "Third stage", RoleId: 73}];

const roles = [
{Id: 71, Name: "Stuff", Key: "STF"},
{Id: 72, Name: "Manager", Key: "MGR"},
{Id: 73, Name: "CEO", Key: "CEO"}];

所以我有"MGR" 键,我想观察stages,其中RoleId 等于经理的角色。

它们是两个可观察对象:阶段和角色。我已经阅读了combineLatest 方法,这可能对我有帮助,但我不知道如何过滤组合结果。

const filteredStages = stages.combineLatest(roles, (s, r) => ({
    s: s,
    r: r
}))
.filter(x => ?);

过滤阶段的正确方法是什么?

【问题讨论】:

  • 你想合并结果,stage + role 在一个对象中吗?
  • 你真的需要为此使用 Observables 吗?我的意思是 stagesroles 是数组,Observables 发射数组或 Observable 分别发射每个项目?
  • @IsaacFerreira 不。我只需要获取阶段包含RoleId: 72 的数组的可观察性,但是我通过使用可观察角色中的"MGR" 键获得此角色ID。
  • @martin 他们从 redux 状态来找我。所以我有两个可观察的:阶段和角色。实际上它们是模型数组。我想得到过滤的阶段数组,其中RoleId 等于 72,并且这个数组应该包含在 observable 中。

标签: javascript rxjs


【解决方案1】:

如果role.Id 不会改变:

stages.filter(stage => stage.RoleId === 72)

如果role.Id 以后可能会更改:

const manager = roles.find(role => role.Key === "MGR");

stages.filter(stage => stage.RoleId === manager.Id)

【讨论】:

  • stages 是可观察到的数组。这意味着stages.filter(s => ...); 将是StageModel[]
  • stages.filter() 将返回 Stage[]
  • 我在说filter 语句中的stage 变量将是一个数组,因为const stagesObservable<StageModel[]>。该数组没有RoleId 属性。这个数组的每个元素都有这个属性。
【解决方案2】:

您需要从roles$流中获取数组中的所有id,然后为所有具有匹配id的阶段切换映射到stages$流:

return roles$.pipe(
  switchMap(roles => {
    let ids = roles.filter(role => role.Key === 'MGR').map(role => role.Id);

    return stage$.pipe(
      filter(stage => ids.indexOf(stage.Id) > -1),
    );
  })
);

【讨论】:

  • [ts] Property 'pipe' does not exist on type 'Observable<RoleModel[]>'.
【解决方案3】:

这是使用 Rxjs 版本 5 语法

我认为创建另一个要过滤的角色的可观察对象是明智的。下面我刚刚通过 Key 属性进行过滤。

const stages$ = Observable.of([
   {Id: 1, Name: "First stage", RoleId: 71},
   {Id: 2, Name: "Second stage", RoleId: 72},
   {Id: 3, Name: "Third stage", RoleId: 73}]);

const roles$ = Observable.of([
   {Id: 71, Name: "Stuff", Key: "STF"},
   {Id: 72, Name: "Manager", Key: "MGR"},
   {Id: 73, Name: "CEO", Key: "CEO"}];

const selectedRole$ = roles$.filter((roles) => {
    return roles.filter(r => r.Key === "MGR");
});

const filteredStages$ = Observable.combineLatest(
  stages$,
  selectedRole$,
  (stagesArr, role) => {
     return stagesArr.filter(s => s.Id === role.Id)
  })
  .subscribe((filteredStages) => console.log('stages', filteredStages);

【讨论】:

  • 我不明白你怎么在这个语句中调用Key属性const selectedRole$ = roles$.filter((r) => r.Key === "MGR"));因为r是一个数组,不包含Key属性。
  • r 是角色$ 数组中的单个对象。和 JavaScript 数组过滤器一样工作
  • Visual Studio Code 给我以下错误信息:[ts] Property 'Key' does not exist on type '{ Id: number; Name: string; Key: string; }[]'. Did you mean 'keys'?
  • 您能否在 stackblitz 中复制您的项目设置?我很乐意提供更多帮助。
  • 你是对的。我已经编辑了 selectedRole$ 输出以在数组本身上使用过滤器。
【解决方案4】:

所以最后我解决了我的问题。我是通过使用map 函数做到的。

const key = 'MGR';

const filteredStages = stages.combineLatest(roles,
(s, r) => ({
   s,
   r
})).map(x => {
    const managerRole = x.r.find(role => role.LookupKey === key);

    return x.s.filter(stage => stage.RoleId !== managerRole.Id);
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 2018-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多