Categories
JavaScript Rxjs

Rxjs Filtering Operators — Distinctness

Spread the love

Rxjs is a library for doing reactive programming. Creation operators are useful for generating data from various data sources to be subscribed to by Observers.

In this article, we’ll look at some filtering operators, including the distinct , distinctUntilChanged , and distinctUntilKeyChanged operators.

distinct

The distinct operator emits the items from the source Observable that are distinct in comparison to previous items from the source.

It takes 2 optional arguments. The first is the keySelector function, which lets us select which value we want to check as distinct.

The second is an optional flushes Observable for flushing the internal HashSet from the operator.

It returns a new Observable that emits values that are distinct.

A simple example would be the following:

import { of } from "rxjs";  
import { distinct } from "rxjs/operators";
of(3, 3, 3, 3, 3, 3, 35, 5, 7, 8, 4, 6, 3, 5, 2, 4, 2)  
  .pipe(distinct())  
  .subscribe(x => console.log(x));

We have the following Observable with duplicate values:

of(3, 3, 3, 3, 3, 3, 35, 5, 7, 8, 4, 6, 3, 5, 2, 4, 2)

The values from it is pipe d to the distinct() operator to filter out duplicate values.

Then we get:

3  
35  
5  
7  
8  
4  
6  
2

from the console.log .

We can also check if some key of an entry is distinct as follows:

import { of } from "rxjs";  
import { distinct } from "rxjs/operators";

const people = [  
  { age: 4, name: "Joe" },  
  { age: 7, name: "Jane" },  
  { age: 5, name: "Jane" }  
];

of(...people)  
  .pipe(distinct(p => p.name))  
  .subscribe(x => console.log(x));

The code above spreads the people array as the arguments of the of operator, which emits the objects in the people array. Then the emitted values are pipe d into the distinct operator, which selects the name property to check for distinctness.

Then only the objects with a different name value is emitted.

In the end, we get:

{age: 4, name: "Joe"}  
{age: 7, name: "Jane"}

As the Observable.

distinctUntilChanged

distinctUntilChanged emits all items emitted from the source Observable that are distinct by comparison from the previous item from the source.

It takes 2 optional arguments, which is a compare function to test if an item is distinct from the previous item. The second argument is the keySelector function to return the value of the key that we want to check.

A simple example would be as follows:

import { of } from "rxjs";  
import { distinctUntilChanged } from "rxjs/operators";
of(1, 1, 5, 5, 6, 7, 8, 8, 8, 8, 9)  
  .pipe(distinctUntilChanged())  
  .subscribe(x => console.log(x));

The values from the of(1, 1, 5, 5, 6, 7, 8, 8, 8, 8, 9) is pipe d to the distinctUntilChanged operator and the previously emitted value is checked against the currently emitted value to see if they’re the same.

Then we get:

1  
5  
6  
7  
8  
9

since the value that’s different from the previously emitted one is emitted.

For Observables that emit objects, we can check if the property’s value is considered the same by passing in a function to the distinctUntilChanged operator as follows:

import { of } from "rxjs";  
import { distinctUntilChanged } from "rxjs/operators";  
const people = [  
  { age: 4, name: "Joe" },  
  { age: 7, name: "Jane" },  
  { age: 5, name: "Jane" }  
];  
of(...people)  
  .pipe(distinctUntilChanged((p, q) => p.name === q.name))  
  .subscribe(x => console.log(x));

The first and last parts work like the previous example. The difference is that now we have the (p, q) => p.name === q.name function to check if the previously emitted name value of the emitted object is the same as the currently emitted one.

Then we get:

{age: 4, name: "Joe"}  
{age: 7, name: "Jane"}

as the output from console.log .

distinctUntilKeyChanged

distinctUntilKeyChanged returns an Observable that emits the value of a source Observable that’s distinct by the comparison with a key of the object emitted previously from the source.

This means that an item will be emitted if the value with the given key is different from the previously emitted object key’s value.

It takes up to 2 arguments. The first is the key , which is a string with the object property to look up for each item.

The second is an optional compare function, which is called to test if an item is distinct from the previously emitted item from the source Observable.

It returns an Observable that emits item from the source Observable with distinct property value from the previously emitted one from the source.

For example, we can rewrite the previous example:

import { of } from "rxjs";  
import { distinctUntilChanged } from "rxjs/operators";  
const people = [  
  { age: 4, name: "Joe" },  
  { age: 7, name: "Jane" },  
  { age: 5, name: "Jane" }  
];  
of(...people)  
  .pipe(distinctUntilChanged((p, q) => p.name === q.name))  
  .subscribe(x => console.log(x));

into:

import { of } from "rxjs";  
import { distinctUntilKeyChanged } from "rxjs/operators";  
const people = [  
  { age: 4, name: "Joe" },  
  { age: 7, name: "Jane" },  
  { age: 5, name: "Jane" }  
];  
of(...people)  
  .pipe(distinctUntilKeyChanged("name"))  
  .subscribe(x => console.log(x));

Then we should get the same result as before. All we did was changing:

distinctUntilChanged((p, q) => p.name === q.name)

to:

distinctUntilKeyChanged("name")

We can use the distinct operator to get the distinct values emitted from a source Observable either by comparing primitive values or values of the properties of an object.

distinctUntilChanged , and distinctUntilKeyChanged let us emit the items from a source Observable that are different from the ones previously emitted by the source Observable. Again, it can compare by the primitive values or the values of the properties of an object.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *