4

I'm having an observable that passes me a json object on which I'm using the distinct operator. I don't want to have duplicates if the entire object is same as before. I can't just use a one comparator like id, as it's id might be same but it's content not.

So I'm currenty stringifying the object and then using distinct and it works fine

Is there a better way to do this?

someObservable
  .startWith(cachedCopy)
  .map(item => JSON.stringify(item))
  .distinct()
  .subscribe(item => {
      //I do some stuff!
     })
Manzur Khan
  • 2,366
  • 4
  • 23
  • 44

3 Answers3

4

Actually I think using JSON.stringify() to compare whether two objects contain the same data is the easiest way to go. If you know the object identity must be different you could use pairwise().filter(pair => pair[0] !== pair[1]) (these must be two different object instances) but this really depends on your use-case and if you can guarantee such condition (usually not in my personal experience and comparing JSONs is "good enough").

Be aware that distinct() passes only really distinct items since the chain was created but in your description you say "duplicates if the entire object is same as before" which seems like you should be using distinctUntilChanged instead.

The distinctUntilChanged operator takes as an optional parameter a comparator function that you can use to check if two objects are the same:

.distinctUntilChanged((prev, curr) => JSON.stringify(prev) === JSON.stringify(curr))
martin
  • 93,354
  • 25
  • 191
  • 226
  • 2
    Stringify is not a good option, in fact it's a wrong one because it is not stable in the order of keys. – Ingo Bürk Feb 03 '18 at 11:12
  • 1
    I would use something like lodash `isEqual` instead of stringify though – Victor Noël Feb 03 '18 at 11:13
  • @IngoBürk https://stackoverflow.com/questions/1068834/object-comparison-in-javascript – martin Feb 03 '18 at 11:35
  • @martin The answer there itself points out that the order is important and the comments correctly explain that object keys aren't ordered, so that link just proves my point. What am I missing? Using stringify just relies on browser implementation details that aren't guaranteed by the spec – Ingo Bürk Feb 03 '18 at 12:07
  • did anyone find a solution? – marianocodes Mar 17 '18 at 05:13
  • 1
    I think stringify is the best option for the majority of simple cases. The number one reason (I think) for wanting to use `distinctUntilChanged` is to minimize unnecessarily running through an observable chain when the source hasn't effectively changed. If your source is the same I would be astonished if the order of keys were ever to change in this context. Unless you're sending data from one browser to another to compare - you're probably just needing to comparing two successive values from your own stream - in which case stringify is optimal. – Simon_Weaver Dec 20 '18 at 05:12
1

When you have lodash in your application anyway, you can simply utilize lodash's isEqual() function, which does a deep comparison and perfectly matches the signature of distinctUntilChanged():

.distinctUntilChanged(isEqual),

Or if you have _ available (which is not recommended anymore these days):

.distinctUntilChanged(_.isEqual),
hoeni
  • 3,031
  • 30
  • 45
  • Why isn't lodash recommenced anymore? The only downside that I'm aware of is bundle size, which can be remedies by using lodash-es (supports tree-shaking, so your code is no larger than it needs to be). – elliottregan Feb 07 '22 at 06:23
  • It's not lodash itself that's not recommended. It's using lodash via `_` that's not recommended. – hoeni Feb 14 '22 at 09:29
0

instead I used Underscore.js Lib,it has a function called unique really saved me https://underscorejs.org/#uniq

1-install it :

$ npm install underscore

2- call it:

import { _ } from 'underscore';

3-use it:

this.allcate = _.uniq(this.allcate);
Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
Asmaa3107
  • 679
  • 1
  • 6
  • 20
  • All this does it reorders an array. Are you saying you use this and then put it through stringify? Or something else. Also changing the order of an array I think qualifies as being a change, so you wouldn't actually want this in most cases. – Simon_Weaver Dec 20 '18 at 05:09