Вычисление среднего значения каждые х мс

1

У меня есть поток, который испускает некоторые данные.

const data$ = Rx
  .Observable
  .interval(500)
  .map(() => Math.random() * 100)

И я хотел бы вычислить среднее значение для всех полученных значений в течение определенного периода времени (например, каждую секунду)

Если поток data$ испускает -2-2-2-4| , Я бы хотел, чтобы результирующий поток был ---2---3|

Как бы вы это сделали с помощью rxjs (версия 5)

Теги:
rxjs
rxjs5

2 ответа

2
Лучший ответ

bufferTime - это путь:

Rx.Observable
  .interval(500)
  .map(() => Math.random() * 100)
  .do(console.log)
  .bufferTime(2000)
  .map(items => {
    return items.reduce((acc, cur) => acc + cur, 0) / items.length;
  })
  .take(3)
  .subscribe(val => {
    console.log('mean: ' + val);
  })
<script src="https://npmcdn.com/@reactivex/[email protected]/dist/global/Rx.js"></script>

Хорошо, точка Maxime действительна. Если вам нужно вычислить среднее значение большого числа значений, используйте windowTime:

var interval = Rx.Observable.interval(2000);

Rx.Observable
  .interval(500)
  .map(() => Math.random() * 100)
  .do(console.log)
  .window(interval)
  .map(win => {
    return win.reduce((acc, cur) => {
      acc.count++;
      acc.sum += cur;
      return acc;
    }, {
      count: 0,
      sum: 0,
    });
  })
  .mergeAll()
  .filter(val => val.count != 0)
  .map(val => val.sum / val.count)
  .take(3)
  .subscribe(val => {
    console.log('mean: ' + val);
  })
<script src="https://npmcdn.com/@reactivex/[email protected]/dist/global/Rx.js"></script>
  • 0
    о круто, спасибо Сергей, это именно то, что я искал :)
1

Ответ Сергея Соколова может быть о'кей, если вам действительно нужно каждую секунду поймать ценность. Но пусть скажем, например, что это скорее будет каждый час, bufferTime потенциально должен сохранить в памяти значения за это время. И здесь, если я понимаю вашу проблему, вам не нужно сохранять эти значения.

Поэтому может быть лучше сделать что-то подобное:

const { Observable } = Rx;

const tick$ = Observable.interval(2000);

const myObs$ = Observable
  .interval(500)
  .map(() => Math.random() * 100)
  .do(x => console.log('Emit ${x}'));

const finalObs$ = tick$
  .withLatestFrom(myObs$)
  .map(([_, val]) => val)
  .do(x => console.warn('Taken ${x}'));

// only to test
finalObs$.take(3).subscribe();

Выход:

Изображение 174551

И каждый console.log здесь просто для отладки, но в вашем окончательном наблюдаемом вы будете иметь только желтое значение из вышеприведенного захвата экрана.

Здесь рабочий Plunkr https://plnkr.co/edit/sR4Dg1gD3Zh2yWUtl0RI?p=preview

  • 0
    Но вы берете только последнее значение, а это не то, что я хочу (я хочу среднее значение). Сергей обновил свой ответ с учетом вашего замечания :)
  • 0
    Хорошо, я неправильно понял, тогда вы должны идти с его ответом наверняка;)
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню