Skip to content

Math

Basic math operators

The provided basic math operators should be self-explanatory.

  • Rx.average emits the running average value.
  • Rx.min /Rx.max emits the running min/max.
  • Rx.sum emits the running numerical sum.
  • Rx.tally emits the count of the number of values that have been emitted

Average, minimum, maximum, sum

These operators will silently ignore values which are supposed to be numbers but aren’t. For example, if you’re using sum, it only knows how to sum numbers. If the input stream contains objects these will be ignored. However, it will attempt to convert strings into numbers.

Useful options when creating these operators are:

  • annotate:boolean: If true, the calculated value is added as a field to the input stream
  • skipIdentical:boolean: If true, it only updates if the min/max/avg changes

Example

import * as Rx from 'ixfx/rx.js';
const largestX = Rx.run(
Rx.From.event(document, `pointermove`),
// Grab just the 'x' value
Rx.Ops.field(`x`),
// Only emit the largest seen value
Rx.Ops.max(),
);
largestX.onValue(x => {
// 'x' will only be the largest seen 'x' value
});

Interpolation

Rx.interpolate outputs a value interpolated from a previous value from the source and the most recent value from the source.

const i = Rx.interpolate(source, { amount: 0.1 }); // interpolate by 10%

The returned reactive only emits a value when the source emits a value. Because of this, you don’t really get the desired interpolation effect, since when the source emits, we set a new target, but we don’t get closer to it over time. What you need to do is ping it at some interval to force it to generate a value. See the example given for using Rx.timeoutPing.

Ranking

Rx.min and Rx.max work great for numerical values, but nothing else. Rx.rank allows you to do a similar kind of thing - finding the preferred value using a custom ranking function.

The ranking function must return a string to denote whether the ‘a’ or ‘b’ parameter is preferred, or ‘eq’ if they are the same.

In the below case, we’re preferring values based on their size property.

const ranked = (a, b) => {
if (a.size > b.size) return `a`;
else if (a.size < b.size) return `b`;
return `eq`;
}
// Emits 'best' value whenever it changes
const rx = Rx.rank(source, ranker);

More

Rx.computeWithPrevious emits a value computed from the current value and the previous value. This is used under-the-hood by Rx.interpolate.