如何根据给定的元素序列过滤数组?

时间:2018-04-10 18:57:46

标签: javascript angular typescript

我想在Angular 5中构建一个管道,根据给定的事件序列过滤我的数据。例如,我们说我的数据是:

["submit","click","go_back","click",....]

我想过滤最多由三个输入提供的数据,因此如果输入1的值是"请单击",我只获得包含所有点击事件的数据(简单),但是,让我们说我的输入是["点击","提交"," go_back"],然后我想过滤数组只有那个序列的出现就在那里:

["click","submit","go_back","click","submit","go_back","click",...]

如何使用数组函数执行此操作?所有三个序列输入都是可选的,我最多只需要三个。 Angular使用管道组件动态过滤它。以下是不起作用的管道代码:

transform(events: any[], event1?: string, event2?: string, event3?: string): any {
  if (!events) { return []; }

  if (event1) {
    if (event2) {
      if (event3) {
        return events.filter((event, i) => {
          // event.event is just the string name of the event
          return (event.event === event3 && events[i-1].event === event2 && events[i-2].event === event1);
        });
      } else {
        console.log("here");
        return events.filter((event, i) => {
          return event.event === event2 && events[i-1].event === event1;
        });
      }
    } else {
      return events.filter((event, i) => event.event === event1);
    }
  } else {
    return events;
  }
}

我能想到的这个以及大多数其他方式最终只会显示第一个事件,虽然我尝试过的一些方法只显示那些第一个事件类型,但也匹配序列(因此在第二个数组中)如果序列存在n次,它将显示"点击" n次。

1 个答案:

答案 0 :(得分:0)

你很亲密,但你只是捕捉了每个匹配模式中的一个元素。例如,而不是:

return events.filter((event, i) => {
    return event.event === event2 && events[i-1].event === event1;
});

你想:

return events.filter((event, i) => {
    return event.event === event2 && events[i-1].event === event1 ||
        events[i+1].event === event2 && event.event === event1;
});

put together a Plunker帮助你。我试着稍微清理一下代码,但随意保留你所拥有的内容并包括我上面展示的其他匹配。

transform(events: Event[], ...pattern: string): Event[] {
    const matches = (event: Event, name: string) => event && event.event === name;
    const matchesPattern = (events: Event[], pattern: string[]) =>
        events.length === pattern.length && events.every((event, i) => matches(event, pattern[i]));

    switch (pattern.length) {
        case 1:
            return events.filter(event => matches(event, pattern[0]));

        case 2:
            return events.filter((event, i) =>
                matchesPattern(events.slice(i, i + 2), pattern) ||
                matchesPattern(events.slice(i - 1, i + 1), pattern));

        case 3:
            return events.filter((event, i) =>
                matchesPattern(events.slice(i, i + 3), pattern) ||
                matchesPattern(events.slice(i - 1, i + 2), pattern) ||
                matchesPattern(events.slice(i - 2, i + 1), pattern));

        default:
            return events;
    }
}