【问题标题】:How can I accumulate number of occurrences of each value over time?如何随着时间的推移累积每个值的出现次数?
【发布时间】:2020-08-05 16:40:59
【问题描述】:

要求

给定一个字母流:'a'、'a'、'b'、'b'、'b'、'c'

发出以下输出,这是到目前为止遇到的每个字母出现次数的总和:

[{ letter: 'a', count : 1 }]
[{ letter: 'a', count : 2 }]
[{ letter: 'a', count : 2 }, { letter: 'b', count : 1 }]
[{ letter: 'a', count : 2 }, { letter: 'b', count : 2 }]
[{ letter: 'a', count : 2 }, { letter: 'b', count : 3 }]
[{ letter: 'a', count : 2 }, { letter: 'b', count : 3 }, { letter: 'c', count : 1 }]

潜在解决方案 #1

类似于https://stackoverflow.com/a/32878533/1188074 - 我最初尝试过这样的事情,但认为它不是很'rxjs like'。根据解决方案 #2 再次查看它,它要简单得多,而且很可能是要走的路。

潜在解决方案 #2

部分尝试:https://stackblitz.com/edit/so-accumulated-letters 基于https://stackoverflow.com/a/53021875/1188074
它在打印单个字母计数时起作用,即:

{ letter: 'a', count : 1 }
{ letter: 'a', count : 2 }
{ letter: 'b', count : 1 }
{ letter: 'b', count : 2 }
{ letter: 'b', count : 3 }
{ letter: 'c', count : 1 }

但是它不跟踪其他以前的字母。我尝试过使用另一个scancombineAll

  1. 我应该使用解决方案 #1 还是 #2 中的方法?
  2. 如果是 #2,我怎样才能让它累积其他字母数?

谢谢

【问题讨论】:

  • 您发布的 stackblitz 链接似乎不起作用
  • @amakhrov 对此感到抱歉,链接已更新
  • 看起来 stackoverflow.com/a/32878533/1188074 已经满足您的需求。如果可变性是一个问题,将countL 函数修改为不可变是微不足道的

标签: rxjs


【解决方案1】:

试试这个:

    const source = ['a', 'b', 'a', 'c', 'd', 'b', 'a'];
    interval(1000)
      .pipe(
        take(7),
        map(i => source[i]),
        groupBy(e => e),
        mergeMap(group => {
          let i = 1;
          return group.pipe(map(e => ({letter: group.key, count: i++})))
        }),
        scan((acc, current) => {
          const index = acc.findIndex(item => item.letter === current.letter);
          if(index > -1) {
            acc[index] = current;
          } else {
            acc.push(current);
          }
          return acc;
        }, [])
      )
      .subscribe(x => console.log(...x))

Demo-1


更新

另一个简单的解决方案是只使用mapscan

source
  .pipe(
    map(e => ({letter: e, count: 1})),
    scan((acc, current) => {
      const index = acc.findIndex(item => item.letter === current.letter);
      if(index > -1) {
        acc[index].count++;
      } else {
        acc.push(current);
      }
      return acc;
    }, [])
  )
  .subscribe(x => console.log(x))

Demo-2

【讨论】:

  • 谢谢,但我需要迄今为止遇到的每个字母的累积计数,并且每次源发出时它们都需要发出,如我问题顶部的示例所示。
  • take 和第一个 map 在这里模拟实时您可以在真实示例中删除它们
  • 嗨,它仍然没有正确的输出。请参阅“潜在解决方案#1”上方的块 - 每行都是一个排放。您的示例每次发射有一个字母计数,我需要对遇到的所有字母进行计数。
  • 啊对于每一个新的排放你想要所有的先例排放?
  • 'a' 由 source observable 发出,输出 observable 发出 { letter: 'a', count : 1 },'b' 由 source observable 发出,输出 observable 发出 { letter: 'a' , count : 1 }, { letter: 'b', count : 1 }, 'b' 再次发出,输出是 { letter: 'a', count : 1 }, { letter: 'b', count : 2 }等。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-03
  • 2019-12-22
相关资源
最近更新 更多