Rxjs - emit if the pair appears - rxjs

Question about rxjs puzzle.
I have a random numbers stream.
the number takes [0-9] numbers. so the stream looks like:
0, 4, 2, 8, 9, 0, 3, 9, ...
I want to emit true if number 9 after 5. In other words, if the pair [5, 9] appears in the stream.
what the pipe should be?
Example code is here:
import { interval } from "rxjs";
import { map } from "rxjs/operators";
const numbers =
interval(500).pipe(map(() => Math.floor(Math.random() * 10))); // it takes [0-9] numbers
numbers.pipe(
// what the pipe should be?
).subscribe(console.log);

You could use the pairwise() operator:
src$.pipe(
pairwise(),
map(([prev, crt]) => prev === 5 && crt === 9)
)

Related

Window on condition

I have an observable of numbers [1, 3, 5, 2, 4, 1, 3] and want to window it by groups of same remainder of the division by two. So, resulting observable of observables will be [[1, 3, 5], [2, 4], [1, 3]]. How can I do it?
The below snippet can produce the results you want, although I'm not sure what you are trying to achieve with this.
The reduce will add numbers to the last subarray, until one of them does not have the same result with the others when divided by two.
The map converts the array of subarrays to array of observables
from([1, 3, 5, 2, 4, 1, 3])
.pipe(
reduce((result, num) => {
const lastArray = result[result.length - 1];
if (lastArray.length > 0 && lastArray[0] % 2 == num % 2) {
lastArray.push(num);
result[result.length - 1] = lastArray;
} else {
result.push([num]);
}
return result;
}, [[]]),
map((array: any[]) => array.map((subarray) => from(subarray)))
)
.subscribe((res) => {
res.forEach((obs, i) =>
obs.subscribe((data) => console.log(data, 'observable ' + i))
);
});
working example

Rxjs operator delay doesn't delay the emitted values from of

I would like to emit a value every second. So I created the following code:
of(1, 2, 3, 4, 5, 6, 7, 8)
.pipe(map(val => val + 10), delay(1000))
.subscribe(console.log);
DEMO
But this code still prints all the values at once with an initial delay of 1 second. But how can you delay every value?
You can achieve that by using RxJS interval function like the following:
interval(1000)
.pipe(map((val) => val + 10))
.subscribe(console.log);

Any way to reset Interval value if a certain condition met?

Suppose I have an array of integers and I want to iterate over this array in a interval of one second, the current second being the index of the array. Once the index reaches the end, I want to reset the interval value. Whats the right approach to achieve this behavior?
Stackblitz example
Code:
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
interval(1000)
.pipe(
tap(second => {
if (array[second]) {
console.log(array[second]);
} else {
//reset interval to run in a cyclic manner?
}
})
).subscribe();
So you want to repeat the same sequence indefinatelly.
import { from, of } from "rxjs";
import { concatMap, repeat, delay } from "rxjs/operators";
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
from(array)
.pipe(
concatMap(second => of(second).pipe(
delay(second * 1000),
)),
repeat(),
)
.subscribe(console.log);
Live demo: https://stackblitz.com/edit/rxjs-interval-pmlj6e

Convert array to sequence of items with flatMap

In RxJS I want to convert an array that I have at some point into a sequence of items that are in the array. I found two ways to do it: Option 1 & 2, which I guess, do the same thing:
const obj = { array: [1, 2, 3, 4, 5] };
const observable = Observable.of(obj);
// Option 1
observable.flatMap(x => {
return Observable.from(x.array);
}).subscribe(console.log);
// Option 2
observable.flatMap(x => x.array).subscribe(console.log);
// Option 3 ?
Are there nicer / better ways that express what I'm doing , I mean without flatMap operator?
I think you've pretty much reached the shortest possible way. The only improvement I might suggest is avoid using callback functions at all:
const obj = { array: [1, 2, 3, 4, 5] };
const observable = Observable.of(obj);
observable
.pluck('array')
.concatAll() // or mergeAll()
.subscribe(console.log);
See live demo: https://jsbin.com/zosonil/edit?js,console

Wrong type with sort in Typescript

var cheapest = leaves.sort((a,b) => <boolean>(<number>a.cost < <number>b.cost));
//also tried without casting
Gives me the following error:
'Error'
message: 'Argument of type '(a: any, b: any) => boolean' is not assignable to parameter of type '(a: any, b: any) => number'.
Type 'boolean' is not assignable to type 'number'.'
How should i fix this?
Edit:
The js code ( original) is taken from :
https://github.com/atomicptr/goap/blob/gh-pages/gameplay/ai/planner.js , which indeed seems to sort by bool instead of number.
This is not how Array.sort works. You need to return a number, but the predicate you've given returns a boolean (The less than (<) operator results in true or false). The sort order is determined by whether the number your function returns is negative, positive, or zero. The MDN example illustrates this well with an example compare function.
function compare(a, b) {
if (a is less than b by some ordering criterion) {
return -1;
}
if (a is greater than b by the ordering criterion) {
return 1;
}
// a must be equal to b
return 0;
}
If you want to sort ascending you can do this with
var cheapest = leaves.sort((a,b) => a.cost - b.cost);
assuming that leaves is typed correctly so a and b have their types correctly inferred.
The comparator function of a sort should return -1, 0, or 1. Returning a boolean instead (effectively 1 or 0) will fail to sort the list correctly!
For example, in Chrome (sort implementations are host-dependent), this line:
[1, 2, 5, 6, 5, 5, 4, 3, 2, 1, 4, 2, 4, 6, 3].sort(function(a, b) { return a < b; })
Produces:
[3, 3, 5, 6, 5, 5, 4, 6, 4, 4, 2, 2, 2, 1, 1]
Which is not sorted!
You should write something like a > b ? 1 : a === b ? 0 : -1 instead
When using Array.prototype.sort(), a comparator function can be used to properly define sorting behaviour. According to the MDN Javascript documentation:
To compare numbers instead of strings, the compare function can simply subtract b from a.
Thus to sort the array 'leaves' in ascending order:
var cheapest = leaves.sort((a,b) => a.cost- b.cost);
With a Typescript generic:
var cheapest = leaves.sort((a,b) => <number>(a.cost- b.cost));

Resources