RxJS - Как я могу отобразить / переключить предметную наблюдаемую и добавить вычисление среднего для каждого испускаемого значения? - PullRequest
0 голосов
/ 02 октября 2018

Я довольно новичок в RxJS и хочу сделать следующее:

Представьте, что я пишу метод для отслеживания температуры во времени.Этот метод наблюдал бы Субъекта, который будет излучать значения, подобные следующему: [12, 49, -2, 26, 5, ...]

Как я могу превратить это в другую Наблюдаемую, которая добавляет среднее значение по времени для каждого значения по мере их поступления?

[
  {
    temperature: 12,
    mean: 12
  },
  {
    temperature: 49,
    mean: 30.5
  },
  {
    temperature: -2,
    mean: 19.67
  },
  {
    temperature: 26,
    mean: 21.25
  },
  {
    temperature: 5,
    mean: 18
  },
  ...
]

Трудность, с которой я сталкиваюсь, заключается в том, что вычисление среднего значения должно выполняться с использованием ВСЕХ предыдущих значений.

Есть ли способ сделать это?На самом деле мне нужно добавить больше данных и рассчитать и другие значения, но это суть того, что мне нужно сделать.

1 Ответ

0 голосов
/ 02 октября 2018

Используйте сканирование, как если бы вы использовали метод Reduce для массива.Передайте начальный аккумулятор с {num: 0, total: 0, mean: 0}, и каждую итерацию увеличивайте num, добавляйте текущую temp к общей температуре и вычисляйте среднее.Думая о наблюдаемых как о массивах, которые происходят со временем, иногда можно их визуализировать.

const { from, timer, zip } = rxjs;
const { scan } = rxjs.operators;

const temps = [12, 49, -2, 26, 5];

// Let's do it with an array
console.log(
  temps.reduce(
    (accumulator, temp) => ({
      num: accumulator.num + 1,
      temp: temp,
      total: accumulator.total + temp,
      mean: (accumulator.total + temp) / (accumulator.num + 1)
    }),
    { num: 0, temp: 0, total: 0, mean: 0 }
  )
);

const temps$ = from(temps);

const timer$ = timer(0, 1500);

var tempsOverTime$ = zip(temps$, timer$, (temp, _) => temp);

// Now let's do the same thing with an observable over time.
tempsOverTime$
  .pipe(
    scan(
      (accumulator, temp) => ({
        num: accumulator.num + 1,
        temp: temp,
        total: accumulator.total + temp,
        mean: (accumulator.total + temp) / (accumulator.num + 1)
      }),
      { num: 0, temp: 0, total: 0, mean: 0 }
    )
  )
  .subscribe(a => {
    console.log({ temp: a.temp, mean: a.mean });
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.min.js"></script>
...