filtering an array of observables efficiently

Related searches

I'm learning about the official angular tutorial (https://angular.io/tutorial/toh-pt4). Excuse me for my low level :(

I'm trying to modify a service that returns the list of heroes ... As observables objects of rxjs, because it is the most efficient way to do it

hero.service.ts
==============

import {Injectable} from '@ angular / core';

import {Observable, of} from 'rxjs';

import {Hero} from './hero';
import {HEROES} from './mock-heroes';
import {MessageService} from './message.service';

@Injectable ({
  providedIn: 'root',
})
export class HeroService {

  constructor (private messageService: MessageService) {}

  getHeroes (): Observable <Hero []> {
    // TODO: send the message _after_ fetching the heroes
    this.messageService.add ('HeroService: fetched heroes');
    return of (HEROES);
  }
}

mock-heroes
===========

import {Hero} from './hero';

export const HEROES: Hero [] = [
  {id: 11, name: 'Mr. Nice '},
  {id: 12, name: 'Narco'},
  {id: 13, name: 'Bombast'},
  {id: 14, name: 'Celeritas'},
  {id: 15, name: 'Magneta'},
  {id: 16, name: 'RubberMan'},
  {id: 17, name: 'Dynama'},
  {id: 18, name: 'Dr IQ'},
  {id: 19, name: 'Magma'},
  {id: 20, name: 'Tornado'}
];

I want to have a service that returns only a hero when I pass an id

import {Injectable} from '@ angular / core';
import {Hero} from './hero';
import {HEROES} from './mock-heroes';
import {Observable, of} from 'rxjs';
import {MessageService} from './message.service';
import {map} from 'rxjs / operators';

@Injectable ({
  providedIn: 'root'
})
export class HeroService {

  private heroes: Observable <Hero []>;

  getHeroes (): Observable <Hero []> {
    this.messageService.add ('HeroService: fetched heroes');
    // return of (HEROES);
    this.heroes = of (HEROES);
    return this.heroes;
  }

  getHeroeById (id: number): Observable <Hero> {
    this.messageService.add ('A hero is queried with id' + id);
    

    return this.heroes.pipe (map (x => x.id === id));
  }

  constructor (private messageService: MessageService) {}

 / * getHeroes (): Hero [] {
    return HEROES;
  } * /

  //builder() { }
}

ERROR in src / app / hero.service.ts (26,5): error TS2322: Type 'Observable ' is not assignable to type 'Observable '.   Type 'boolean' is not assignable to type 'Hero'. src / app / hero.service.ts (26.40): TS2339 error: Property 'id' does not exist on type 'Hero []'.

Can you help me ?

You have a couple options. You can use Array.find() or Array.filter()

Array.filter()

getHeroeById (id: number): Observable <Hero> {
  this.messageService.add('A hero is queried with id: ' + id);

  // Filter heroes to get heroById
  return this.heroes.filter(x => x.id == id)[0];
}

Array.find()

getHeroeById (id: number): Observable <Hero> {
  this.messageService.add('A hero is queried with id: ' + id);

  // Find hero by Id.
  return this.heroes.find(x => x.id == this.personId);
}

RxJS Patterns: Efficiency and Performance, If you are already familiar with the method Array.prototype.filter , then current value with the previous value of the source Observable, and if� The first input, InputArray needs to be a single-dimension string array. This is the array that you want to filter. ValueToFilterOn is the filter string. GetValuesThatMatch is an optional boolean parameter that has a default value of True.

You want to return the hero in the hero list with the matching id, try replacing

return this.heroes.pipe (map (x => x.id === id));

by

return this.heroes.pipe (map (heroes => heroes.find( hero => hero.id === id));

Manipulating Flat Arrays / Mike Bostock / Observable, It's most efficient if your data is loaded directly into a columnar Since filtering arrays will be a common task, we can make a helper filter� When the underlying myObservableArray changes, or whenever any observable accessed during the mapping/filtering changes, the output array will be recomputed efficiently, meaning that the map/filter callbacks will only be invoked for the affected items.

your issue is this line:

return this.heroes.pipe (map (x => x.id === id));

you are using the rx map operator, which operates on and transforms the items in the stream, and the stream item in the case is the actual array of heroes. You're returning the result of the test of whether some nonexistent id property of the array is equal to the id parameter, which is a boolean value. This is why you're seeing the errors you are.

You should use the array find operator on the array in stream in this case since you want to find that item in the array, like so:

return this.heroes.pipe (map (heroes => heroes.find(h => h.id === id)));

this way, you're returning the actual result of the array find operation within the rx map transform operation.

Next thing, you don't initialize your heroes obersvable until getHeroes() is called. This may be intentional, but it seems like you should instead do it in the constructor so getHeroeById() can be safely called first.

Speed Up JavaScript Array Processing | by Kevin Ghadyani, JavaScript Arrays are great when you only have a few items, but when you have a large amount of data or want to do complex transformations with lots of map, filter, and Transducers: Efficient Data Processing Pipelines in JavaScript Array methods return arrays, not observables containing the value of� combineLatest(this.states$, this.filter$).pipe(map(([states, filterString]) => // FILTER HERE)); This leads us to the following code, using the array filter function only to keep data that contains the filterString. Note that we use .toLowerCase() for the comparison, so we make the search case-insensitive:

Dynamic filtering with RxJs and Angular forms — A tutorial, In this tutorial, we're going to see how to implement a data filter using RxJs What could b the right way of doing efficient filtering in this case Of course, this is just an example, and any Observable or static data would work as well: This leads us to the following code, using the array filter function only to� By Rod McBride . Usually, when filtering data from a database or a collection, you are comparing one or two values to a list of many. However, with a recent application, I found myself needing to filter a list of items using another list.

Knockout Projections – a plugin for efficient observable array , Write myObservableArray.filter(someFilterFunction) to get a new, read-only array- valued observable containing a subset of the input items. When� This is not really speicifc for observableArrays, but all observables, but it is usually most evident with computed observables which depend on observableArrays and return a different array. Again, consider the following example, which allows users to filter the teams based on the text entered into a textbox (quite a common scenario):

In order to use map and filter in a chaining sequence we have flattened the results of our Observable using flatMap. Since filter accepts an Observable, and not an array, we have to convert our array of JSON objects from data.json () to an Observable stream. This is done with flatMap.

Comments
  • You should use find, because it will be return the hero when it finds the first id. The filter, will loop through all heroes, and compare the id to your id even though it could have found the hero at position one. In short, find will return as soon as the condition is matched.