Remove Duplicates from an Array of GeoFire Objects

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
8
down vote

favorite
1












I am working with Geofire and Firebase on Angular 6 to store locations and unfortunately it's storing a lot of duplicates this is an example (console logging my variable currentHits):



0: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
1: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
2: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
3: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
4: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
5: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
6: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"
7: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"
8: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"


Location basically is an array of latitude and longitude used to calculate distance, in id 0, 1 and 2 its the same coordinates, and 3,4 and 5 are also the same, ...



This is what I want to get:



0: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
1: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
2: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"


(Optional) this is how It stores these locations:



 ...
hits = new BehaviorSubject()

...
queryHits(...)
....
let hit =
location: location,
distance: distance.toFixed(2),
url:img


let currentHits = this.hits.value
currentHits.push(hit)
this.hits.next(currentHits)
....



It's true that this question has probably already been asked and I have been digging through all the similar questions and found these functions:



1. RemoveDuplicates()



function removeDuplicates(arr)
let unique_array =
for(let i = 0;i < arr.length; i++)
if(unique_array.indexOf(arr[i]) == -1)
unique_array.push(arr[i])


return unique_array


var newlist = removeDuplicates(list)


It didn't work I get the same list with duplicates.



2. arrUnique:



function arrUnique(arr) 
var cleaned = ;
arr.forEach(function(itm)
var unique = true;
cleaned.forEach(function(itm2)
if (_.isEqual(itm, itm2)) unique = false;
);
if (unique) cleaned.push(itm);
);
return cleaned;


var newlist= arrUnique(list);


Also, it didn't work..



3. onlyUnique



 onlyUnique(value, index, self) 
return self.indexOf(value) === index;


var newlist = list.filter(onlyUnique)


Unfortunately it didn't work...



These are some of the answers given to similar problem to remove duplicates from an array and none of them worked. I don't understand why they won't work for my type of array, If anyone has an idea or knows why would be very helpful.










share|improve this question























  • Your approaches didn't work because all objects, even if it shares all the same key/values, are different instances (unless Singleton which this isn't)
    – Mark
    25 mins ago











  • Can you share sample JSON. That would be better for us
    – Rajesh
    24 mins ago






  • 2




    If you remove the erroneous "JSON" from your title, there is an identical question here: Remove duplicates from an array of objects in JavaScript with 34 answers. Surely one of them does the job?
    – RobG
    23 mins ago






  • 2




    Possible duplicate of Remove duplicates from an array of objects in JavaScript
    – David
    22 mins ago






  • 1




    you can't compare objects this way : === return false
    – Martial
    22 mins ago














up vote
8
down vote

favorite
1












I am working with Geofire and Firebase on Angular 6 to store locations and unfortunately it's storing a lot of duplicates this is an example (console logging my variable currentHits):



0: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
1: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
2: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
3: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
4: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
5: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
6: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"
7: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"
8: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"


Location basically is an array of latitude and longitude used to calculate distance, in id 0, 1 and 2 its the same coordinates, and 3,4 and 5 are also the same, ...



This is what I want to get:



0: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
1: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
2: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"


(Optional) this is how It stores these locations:



 ...
hits = new BehaviorSubject()

...
queryHits(...)
....
let hit =
location: location,
distance: distance.toFixed(2),
url:img


let currentHits = this.hits.value
currentHits.push(hit)
this.hits.next(currentHits)
....



It's true that this question has probably already been asked and I have been digging through all the similar questions and found these functions:



1. RemoveDuplicates()



function removeDuplicates(arr)
let unique_array =
for(let i = 0;i < arr.length; i++)
if(unique_array.indexOf(arr[i]) == -1)
unique_array.push(arr[i])


return unique_array


var newlist = removeDuplicates(list)


It didn't work I get the same list with duplicates.



2. arrUnique:



function arrUnique(arr) 
var cleaned = ;
arr.forEach(function(itm)
var unique = true;
cleaned.forEach(function(itm2)
if (_.isEqual(itm, itm2)) unique = false;
);
if (unique) cleaned.push(itm);
);
return cleaned;


var newlist= arrUnique(list);


Also, it didn't work..



3. onlyUnique



 onlyUnique(value, index, self) 
return self.indexOf(value) === index;


var newlist = list.filter(onlyUnique)


Unfortunately it didn't work...



These are some of the answers given to similar problem to remove duplicates from an array and none of them worked. I don't understand why they won't work for my type of array, If anyone has an idea or knows why would be very helpful.










share|improve this question























  • Your approaches didn't work because all objects, even if it shares all the same key/values, are different instances (unless Singleton which this isn't)
    – Mark
    25 mins ago











  • Can you share sample JSON. That would be better for us
    – Rajesh
    24 mins ago






  • 2




    If you remove the erroneous "JSON" from your title, there is an identical question here: Remove duplicates from an array of objects in JavaScript with 34 answers. Surely one of them does the job?
    – RobG
    23 mins ago






  • 2




    Possible duplicate of Remove duplicates from an array of objects in JavaScript
    – David
    22 mins ago






  • 1




    you can't compare objects this way : === return false
    – Martial
    22 mins ago












up vote
8
down vote

favorite
1









up vote
8
down vote

favorite
1






1





I am working with Geofire and Firebase on Angular 6 to store locations and unfortunately it's storing a lot of duplicates this is an example (console logging my variable currentHits):



0: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
1: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
2: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
3: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
4: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
5: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
6: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"
7: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"
8: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"


Location basically is an array of latitude and longitude used to calculate distance, in id 0, 1 and 2 its the same coordinates, and 3,4 and 5 are also the same, ...



This is what I want to get:



0: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
1: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
2: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"


(Optional) this is how It stores these locations:



 ...
hits = new BehaviorSubject()

...
queryHits(...)
....
let hit =
location: location,
distance: distance.toFixed(2),
url:img


let currentHits = this.hits.value
currentHits.push(hit)
this.hits.next(currentHits)
....



It's true that this question has probably already been asked and I have been digging through all the similar questions and found these functions:



1. RemoveDuplicates()



function removeDuplicates(arr)
let unique_array =
for(let i = 0;i < arr.length; i++)
if(unique_array.indexOf(arr[i]) == -1)
unique_array.push(arr[i])


return unique_array


var newlist = removeDuplicates(list)


It didn't work I get the same list with duplicates.



2. arrUnique:



function arrUnique(arr) 
var cleaned = ;
arr.forEach(function(itm)
var unique = true;
cleaned.forEach(function(itm2)
if (_.isEqual(itm, itm2)) unique = false;
);
if (unique) cleaned.push(itm);
);
return cleaned;


var newlist= arrUnique(list);


Also, it didn't work..



3. onlyUnique



 onlyUnique(value, index, self) 
return self.indexOf(value) === index;


var newlist = list.filter(onlyUnique)


Unfortunately it didn't work...



These are some of the answers given to similar problem to remove duplicates from an array and none of them worked. I don't understand why they won't work for my type of array, If anyone has an idea or knows why would be very helpful.










share|improve this question















I am working with Geofire and Firebase on Angular 6 to store locations and unfortunately it's storing a lot of duplicates this is an example (console logging my variable currentHits):



0: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
1: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
2: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
3: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
4: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
5: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
6: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"
7: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"
8: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"


Location basically is an array of latitude and longitude used to calculate distance, in id 0, 1 and 2 its the same coordinates, and 3,4 and 5 are also the same, ...



This is what I want to get:



0: location: Array(2), distance: "48.84", url: "assets/imgs/fix.png"
1: location: Array(2), distance: "48.85", url: "assets/imgs/free.png"
2: location: Array(2), distance: "48.87", url: "assets/imgs/low.png"


(Optional) this is how It stores these locations:



 ...
hits = new BehaviorSubject()

...
queryHits(...)
....
let hit =
location: location,
distance: distance.toFixed(2),
url:img


let currentHits = this.hits.value
currentHits.push(hit)
this.hits.next(currentHits)
....



It's true that this question has probably already been asked and I have been digging through all the similar questions and found these functions:



1. RemoveDuplicates()



function removeDuplicates(arr)
let unique_array =
for(let i = 0;i < arr.length; i++)
if(unique_array.indexOf(arr[i]) == -1)
unique_array.push(arr[i])


return unique_array


var newlist = removeDuplicates(list)


It didn't work I get the same list with duplicates.



2. arrUnique:



function arrUnique(arr) 
var cleaned = ;
arr.forEach(function(itm)
var unique = true;
cleaned.forEach(function(itm2)
if (_.isEqual(itm, itm2)) unique = false;
);
if (unique) cleaned.push(itm);
);
return cleaned;


var newlist= arrUnique(list);


Also, it didn't work..



3. onlyUnique



 onlyUnique(value, index, self) 
return self.indexOf(value) === index;


var newlist = list.filter(onlyUnique)


Unfortunately it didn't work...



These are some of the answers given to similar problem to remove duplicates from an array and none of them worked. I don't understand why they won't work for my type of array, If anyone has an idea or knows why would be very helpful.







javascript angular firebase geofire






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 31 secs ago

























asked 33 mins ago









Programmer Man

367114




367114











  • Your approaches didn't work because all objects, even if it shares all the same key/values, are different instances (unless Singleton which this isn't)
    – Mark
    25 mins ago











  • Can you share sample JSON. That would be better for us
    – Rajesh
    24 mins ago






  • 2




    If you remove the erroneous "JSON" from your title, there is an identical question here: Remove duplicates from an array of objects in JavaScript with 34 answers. Surely one of them does the job?
    – RobG
    23 mins ago






  • 2




    Possible duplicate of Remove duplicates from an array of objects in JavaScript
    – David
    22 mins ago






  • 1




    you can't compare objects this way : === return false
    – Martial
    22 mins ago
















  • Your approaches didn't work because all objects, even if it shares all the same key/values, are different instances (unless Singleton which this isn't)
    – Mark
    25 mins ago











  • Can you share sample JSON. That would be better for us
    – Rajesh
    24 mins ago






  • 2




    If you remove the erroneous "JSON" from your title, there is an identical question here: Remove duplicates from an array of objects in JavaScript with 34 answers. Surely one of them does the job?
    – RobG
    23 mins ago






  • 2




    Possible duplicate of Remove duplicates from an array of objects in JavaScript
    – David
    22 mins ago






  • 1




    you can't compare objects this way : === return false
    – Martial
    22 mins ago















Your approaches didn't work because all objects, even if it shares all the same key/values, are different instances (unless Singleton which this isn't)
– Mark
25 mins ago





Your approaches didn't work because all objects, even if it shares all the same key/values, are different instances (unless Singleton which this isn't)
– Mark
25 mins ago













Can you share sample JSON. That would be better for us
– Rajesh
24 mins ago




Can you share sample JSON. That would be better for us
– Rajesh
24 mins ago




2




2




If you remove the erroneous "JSON" from your title, there is an identical question here: Remove duplicates from an array of objects in JavaScript with 34 answers. Surely one of them does the job?
– RobG
23 mins ago




If you remove the erroneous "JSON" from your title, there is an identical question here: Remove duplicates from an array of objects in JavaScript with 34 answers. Surely one of them does the job?
– RobG
23 mins ago




2




2




Possible duplicate of Remove duplicates from an array of objects in JavaScript
– David
22 mins ago




Possible duplicate of Remove duplicates from an array of objects in JavaScript
– David
22 mins ago




1




1




you can't compare objects this way : === return false
– Martial
22 mins ago




you can't compare objects this way : === return false
– Martial
22 mins ago












5 Answers
5






active

oldest

votes

















up vote
3
down vote













You could use a set to store and check for duplicate values.



const removeDuplicates = arr => 
let matches = new Set();
return arr.filter(elem =>
const distance = elem;
if(matches.has(distance))
return false;
else
matches.add(distance);
return true;

)



Bear in mind that using this approach you may remove results where the distance is the same but the co-ordinates differ. If that causes an issue for you then you'd need to also check against the lat/lng pair.






share|improve this answer



























    up vote
    1
    down vote













    Problem here is comparing Objects. Two objects are never equal unless both are referencing to same Object.



    Example:



     === // false

    // Two objects are equal only if they are referencing to same object
    var a = ;
    a === a; // true


    It is clear from your problem that you are facing the first case. Among the solutions you tested Solution 1 and Solution 3 are failing because of this reason as indexOf does === comparision.



    But Solution 2 should have worked on your example as it does a deep comparision as explained here. https://lodash.com/docs#isEqual.



    PS: It might be a simple typo i have observed in Solution 2 cleaned.,push(itm);, there is an extra comma. Hoping that is not the case I am moving ahead



    So i guess the issue is inside your location array, if you can give the contents of location array we should be able to provide better solution. Or as others suggested you can filter based on a single key of the object like id or distance, instead of comparing the whole object






    share|improve this answer
















    • 1




      Yes, though solution 2 could be written a little simpler using if (!_.isEqual(itm, itm2)) cleaned.push(itm);. ;-)
      – RobG
      6 mins ago

















    up vote
    1
    down vote













    You could always check before you add the hits to make sure there are no repeats. paired with Adam's answer, before sending values to the db use the pipe on your Subject distinctUntilChanged. I would also recommend adding an ID property to your objects, it will make them easier to sort/look up/stop repeats.



    let currentHits = this.hits.pipe(distinctUntilChanged();


    here is the example from the link



    import from from 'rxjs';
    import distinctUntilChanged from 'rxjs/operators';

    const sampleObject = name: 'Test' ;

    //Objects must be same reference
    const myArrayWithDuplicateObjects = from([ sampleObject, sampleObject, sampleObject ]);

    //only out distinct objects, based on last emitted value
    const nonDistinctObjects = myArrayWithDuplicateObjects.pipe(distinctUntilChanged())

    //output: 'DISTINCT OBJECTS: name: 'Test' .subscribe(val => console.log('DISTINCT OBJECTS:', val));





    share|improve this answer






















    • This approach is soo gooad but I am getting error ts] The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<>
      – Programmer Man
      17 mins ago










    • the list I showd on my question actually can be logged from console.log(this.hits.value) or console.log(currentHits)
      – Programmer Man
      16 mins ago










    • @ProgrammerMan it's probably a bad import from rxjs. If you are using rxjs 6, import distinctUntilChanged from 'rxjs/operators'
      – FussinHussin
      12 mins ago










    • Thank you for checking I have changed the import as you said and now getting this Argument of type '(value: any) => any' is not assignable to parameter of type '(x: any, y: any) => boolean'. Type 'any' is not assignable to type 'boolean'.
      – Programmer Man
      10 mins ago










    • @ProgrammerMan my apologies, actually you don't need to pass value in the operator, i'll update the answer
      – FussinHussin
      8 mins ago

















    up vote
    1
    down vote













    You can use following approach:



    Idea:



    • You can create your own data structure and have a hashMap to save values.

    • Since you have location data, you can use longitude|latitude as your key name as it will be unique.

    • Then expose some functions say, add that will check if value exists, override else add.

    • Also create a property, say value that would return the list of locations.

    Note: Above behavior can be achieved using Set as well. If you cannot use ES6 features, then this is one way that is extensible and easy.






    function MyList() 
    var locations = ;

    this.add = function(value) ');
    locations[key] = value;


    Object.defineProperty(this, 'value',
    get: function()
    return Object.keys(locations).map(function(key) return locations[key] )

    )


    var locations = new MyList();

    locations.add(location: [123.12, 456.23], name: 'test 1' );
    locations.add(location: [123.16, 451.23], name: 'test 2' );
    locations.add(location: [123.12, 456.23], name: 'test 1' );
    locations.add(location: [100.12, 456.23], name: 'test 3' );
    locations.add(location: [123.12, 456.23], name: 'test 1' );
    locations.add(location: [123.12, 400.23], name: 'test 4' );

    console.log(locations.value)





    Typescript version for more readability:





    interface ILocation 
    location: Array<number>
    [key: string]: any;


    interface IList
    [key: string]: ILocation


    class MyList
    private locations: IList = ;

    public add(value: ILocation) ');
    this.locations[key] = value;


    public get value(): Array<ILocation>
    return Object.keys(locations).map(function(key) return locations[key] )








    share






















    • This looks so nice can you translate it to typescript?? because when you say this.add where do you declare add?
      – Programmer Man
      6 mins ago










    • @ProgrammerMan I have added a typescript code sample. Its not runnable though. Hope it helps you!
      – Rajesh
      27 secs ago

















    up vote
    0
    down vote













    Perhaps you would want to use a library such as lodash which has a wide set of functions regarding all types of collections.



    let newArr = _.uniqWith(myArr, _.isEqual);


    uniqWith with the help of isEqual can get what you want.



    Here is fiddle to that solution






    share|improve this answer




















      Your Answer





      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52480479%2fremove-duplicates-from-an-array-of-geofire-objects%23new-answer', 'question_page');

      );

      Post as a guest






























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      3
      down vote













      You could use a set to store and check for duplicate values.



      const removeDuplicates = arr => 
      let matches = new Set();
      return arr.filter(elem =>
      const distance = elem;
      if(matches.has(distance))
      return false;
      else
      matches.add(distance);
      return true;

      )



      Bear in mind that using this approach you may remove results where the distance is the same but the co-ordinates differ. If that causes an issue for you then you'd need to also check against the lat/lng pair.






      share|improve this answer
























        up vote
        3
        down vote













        You could use a set to store and check for duplicate values.



        const removeDuplicates = arr => 
        let matches = new Set();
        return arr.filter(elem =>
        const distance = elem;
        if(matches.has(distance))
        return false;
        else
        matches.add(distance);
        return true;

        )



        Bear in mind that using this approach you may remove results where the distance is the same but the co-ordinates differ. If that causes an issue for you then you'd need to also check against the lat/lng pair.






        share|improve this answer






















          up vote
          3
          down vote










          up vote
          3
          down vote









          You could use a set to store and check for duplicate values.



          const removeDuplicates = arr => 
          let matches = new Set();
          return arr.filter(elem =>
          const distance = elem;
          if(matches.has(distance))
          return false;
          else
          matches.add(distance);
          return true;

          )



          Bear in mind that using this approach you may remove results where the distance is the same but the co-ordinates differ. If that causes an issue for you then you'd need to also check against the lat/lng pair.






          share|improve this answer












          You could use a set to store and check for duplicate values.



          const removeDuplicates = arr => 
          let matches = new Set();
          return arr.filter(elem =>
          const distance = elem;
          if(matches.has(distance))
          return false;
          else
          matches.add(distance);
          return true;

          )



          Bear in mind that using this approach you may remove results where the distance is the same but the co-ordinates differ. If that causes an issue for you then you'd need to also check against the lat/lng pair.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 29 mins ago









          Adam

          69439




          69439






















              up vote
              1
              down vote













              Problem here is comparing Objects. Two objects are never equal unless both are referencing to same Object.



              Example:



               === // false

              // Two objects are equal only if they are referencing to same object
              var a = ;
              a === a; // true


              It is clear from your problem that you are facing the first case. Among the solutions you tested Solution 1 and Solution 3 are failing because of this reason as indexOf does === comparision.



              But Solution 2 should have worked on your example as it does a deep comparision as explained here. https://lodash.com/docs#isEqual.



              PS: It might be a simple typo i have observed in Solution 2 cleaned.,push(itm);, there is an extra comma. Hoping that is not the case I am moving ahead



              So i guess the issue is inside your location array, if you can give the contents of location array we should be able to provide better solution. Or as others suggested you can filter based on a single key of the object like id or distance, instead of comparing the whole object






              share|improve this answer
















              • 1




                Yes, though solution 2 could be written a little simpler using if (!_.isEqual(itm, itm2)) cleaned.push(itm);. ;-)
                – RobG
                6 mins ago














              up vote
              1
              down vote













              Problem here is comparing Objects. Two objects are never equal unless both are referencing to same Object.



              Example:



               === // false

              // Two objects are equal only if they are referencing to same object
              var a = ;
              a === a; // true


              It is clear from your problem that you are facing the first case. Among the solutions you tested Solution 1 and Solution 3 are failing because of this reason as indexOf does === comparision.



              But Solution 2 should have worked on your example as it does a deep comparision as explained here. https://lodash.com/docs#isEqual.



              PS: It might be a simple typo i have observed in Solution 2 cleaned.,push(itm);, there is an extra comma. Hoping that is not the case I am moving ahead



              So i guess the issue is inside your location array, if you can give the contents of location array we should be able to provide better solution. Or as others suggested you can filter based on a single key of the object like id or distance, instead of comparing the whole object






              share|improve this answer
















              • 1




                Yes, though solution 2 could be written a little simpler using if (!_.isEqual(itm, itm2)) cleaned.push(itm);. ;-)
                – RobG
                6 mins ago












              up vote
              1
              down vote










              up vote
              1
              down vote









              Problem here is comparing Objects. Two objects are never equal unless both are referencing to same Object.



              Example:



               === // false

              // Two objects are equal only if they are referencing to same object
              var a = ;
              a === a; // true


              It is clear from your problem that you are facing the first case. Among the solutions you tested Solution 1 and Solution 3 are failing because of this reason as indexOf does === comparision.



              But Solution 2 should have worked on your example as it does a deep comparision as explained here. https://lodash.com/docs#isEqual.



              PS: It might be a simple typo i have observed in Solution 2 cleaned.,push(itm);, there is an extra comma. Hoping that is not the case I am moving ahead



              So i guess the issue is inside your location array, if you can give the contents of location array we should be able to provide better solution. Or as others suggested you can filter based on a single key of the object like id or distance, instead of comparing the whole object






              share|improve this answer












              Problem here is comparing Objects. Two objects are never equal unless both are referencing to same Object.



              Example:



               === // false

              // Two objects are equal only if they are referencing to same object
              var a = ;
              a === a; // true


              It is clear from your problem that you are facing the first case. Among the solutions you tested Solution 1 and Solution 3 are failing because of this reason as indexOf does === comparision.



              But Solution 2 should have worked on your example as it does a deep comparision as explained here. https://lodash.com/docs#isEqual.



              PS: It might be a simple typo i have observed in Solution 2 cleaned.,push(itm);, there is an extra comma. Hoping that is not the case I am moving ahead



              So i guess the issue is inside your location array, if you can give the contents of location array we should be able to provide better solution. Or as others suggested you can filter based on a single key of the object like id or distance, instead of comparing the whole object







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered 12 mins ago









              AvcS

              760310




              760310







              • 1




                Yes, though solution 2 could be written a little simpler using if (!_.isEqual(itm, itm2)) cleaned.push(itm);. ;-)
                – RobG
                6 mins ago












              • 1




                Yes, though solution 2 could be written a little simpler using if (!_.isEqual(itm, itm2)) cleaned.push(itm);. ;-)
                – RobG
                6 mins ago







              1




              1




              Yes, though solution 2 could be written a little simpler using if (!_.isEqual(itm, itm2)) cleaned.push(itm);. ;-)
              – RobG
              6 mins ago




              Yes, though solution 2 could be written a little simpler using if (!_.isEqual(itm, itm2)) cleaned.push(itm);. ;-)
              – RobG
              6 mins ago










              up vote
              1
              down vote













              You could always check before you add the hits to make sure there are no repeats. paired with Adam's answer, before sending values to the db use the pipe on your Subject distinctUntilChanged. I would also recommend adding an ID property to your objects, it will make them easier to sort/look up/stop repeats.



              let currentHits = this.hits.pipe(distinctUntilChanged();


              here is the example from the link



              import from from 'rxjs';
              import distinctUntilChanged from 'rxjs/operators';

              const sampleObject = name: 'Test' ;

              //Objects must be same reference
              const myArrayWithDuplicateObjects = from([ sampleObject, sampleObject, sampleObject ]);

              //only out distinct objects, based on last emitted value
              const nonDistinctObjects = myArrayWithDuplicateObjects.pipe(distinctUntilChanged())

              //output: 'DISTINCT OBJECTS: name: 'Test' .subscribe(val => console.log('DISTINCT OBJECTS:', val));





              share|improve this answer






















              • This approach is soo gooad but I am getting error ts] The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<>
                – Programmer Man
                17 mins ago










              • the list I showd on my question actually can be logged from console.log(this.hits.value) or console.log(currentHits)
                – Programmer Man
                16 mins ago










              • @ProgrammerMan it's probably a bad import from rxjs. If you are using rxjs 6, import distinctUntilChanged from 'rxjs/operators'
                – FussinHussin
                12 mins ago










              • Thank you for checking I have changed the import as you said and now getting this Argument of type '(value: any) => any' is not assignable to parameter of type '(x: any, y: any) => boolean'. Type 'any' is not assignable to type 'boolean'.
                – Programmer Man
                10 mins ago










              • @ProgrammerMan my apologies, actually you don't need to pass value in the operator, i'll update the answer
                – FussinHussin
                8 mins ago














              up vote
              1
              down vote













              You could always check before you add the hits to make sure there are no repeats. paired with Adam's answer, before sending values to the db use the pipe on your Subject distinctUntilChanged. I would also recommend adding an ID property to your objects, it will make them easier to sort/look up/stop repeats.



              let currentHits = this.hits.pipe(distinctUntilChanged();


              here is the example from the link



              import from from 'rxjs';
              import distinctUntilChanged from 'rxjs/operators';

              const sampleObject = name: 'Test' ;

              //Objects must be same reference
              const myArrayWithDuplicateObjects = from([ sampleObject, sampleObject, sampleObject ]);

              //only out distinct objects, based on last emitted value
              const nonDistinctObjects = myArrayWithDuplicateObjects.pipe(distinctUntilChanged())

              //output: 'DISTINCT OBJECTS: name: 'Test' .subscribe(val => console.log('DISTINCT OBJECTS:', val));





              share|improve this answer






















              • This approach is soo gooad but I am getting error ts] The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<>
                – Programmer Man
                17 mins ago










              • the list I showd on my question actually can be logged from console.log(this.hits.value) or console.log(currentHits)
                – Programmer Man
                16 mins ago










              • @ProgrammerMan it's probably a bad import from rxjs. If you are using rxjs 6, import distinctUntilChanged from 'rxjs/operators'
                – FussinHussin
                12 mins ago










              • Thank you for checking I have changed the import as you said and now getting this Argument of type '(value: any) => any' is not assignable to parameter of type '(x: any, y: any) => boolean'. Type 'any' is not assignable to type 'boolean'.
                – Programmer Man
                10 mins ago










              • @ProgrammerMan my apologies, actually you don't need to pass value in the operator, i'll update the answer
                – FussinHussin
                8 mins ago












              up vote
              1
              down vote










              up vote
              1
              down vote









              You could always check before you add the hits to make sure there are no repeats. paired with Adam's answer, before sending values to the db use the pipe on your Subject distinctUntilChanged. I would also recommend adding an ID property to your objects, it will make them easier to sort/look up/stop repeats.



              let currentHits = this.hits.pipe(distinctUntilChanged();


              here is the example from the link



              import from from 'rxjs';
              import distinctUntilChanged from 'rxjs/operators';

              const sampleObject = name: 'Test' ;

              //Objects must be same reference
              const myArrayWithDuplicateObjects = from([ sampleObject, sampleObject, sampleObject ]);

              //only out distinct objects, based on last emitted value
              const nonDistinctObjects = myArrayWithDuplicateObjects.pipe(distinctUntilChanged())

              //output: 'DISTINCT OBJECTS: name: 'Test' .subscribe(val => console.log('DISTINCT OBJECTS:', val));





              share|improve this answer














              You could always check before you add the hits to make sure there are no repeats. paired with Adam's answer, before sending values to the db use the pipe on your Subject distinctUntilChanged. I would also recommend adding an ID property to your objects, it will make them easier to sort/look up/stop repeats.



              let currentHits = this.hits.pipe(distinctUntilChanged();


              here is the example from the link



              import from from 'rxjs';
              import distinctUntilChanged from 'rxjs/operators';

              const sampleObject = name: 'Test' ;

              //Objects must be same reference
              const myArrayWithDuplicateObjects = from([ sampleObject, sampleObject, sampleObject ]);

              //only out distinct objects, based on last emitted value
              const nonDistinctObjects = myArrayWithDuplicateObjects.pipe(distinctUntilChanged())

              //output: 'DISTINCT OBJECTS: name: 'Test' .subscribe(val => console.log('DISTINCT OBJECTS:', val));






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited 6 mins ago

























              answered 20 mins ago









              FussinHussin

              565325




              565325











              • This approach is soo gooad but I am getting error ts] The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<>
                – Programmer Man
                17 mins ago










              • the list I showd on my question actually can be logged from console.log(this.hits.value) or console.log(currentHits)
                – Programmer Man
                16 mins ago










              • @ProgrammerMan it's probably a bad import from rxjs. If you are using rxjs 6, import distinctUntilChanged from 'rxjs/operators'
                – FussinHussin
                12 mins ago










              • Thank you for checking I have changed the import as you said and now getting this Argument of type '(value: any) => any' is not assignable to parameter of type '(x: any, y: any) => boolean'. Type 'any' is not assignable to type 'boolean'.
                – Programmer Man
                10 mins ago










              • @ProgrammerMan my apologies, actually you don't need to pass value in the operator, i'll update the answer
                – FussinHussin
                8 mins ago
















              • This approach is soo gooad but I am getting error ts] The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<>
                – Programmer Man
                17 mins ago










              • the list I showd on my question actually can be logged from console.log(this.hits.value) or console.log(currentHits)
                – Programmer Man
                16 mins ago










              • @ProgrammerMan it's probably a bad import from rxjs. If you are using rxjs 6, import distinctUntilChanged from 'rxjs/operators'
                – FussinHussin
                12 mins ago










              • Thank you for checking I have changed the import as you said and now getting this Argument of type '(value: any) => any' is not assignable to parameter of type '(x: any, y: any) => boolean'. Type 'any' is not assignable to type 'boolean'.
                – Programmer Man
                10 mins ago










              • @ProgrammerMan my apologies, actually you don't need to pass value in the operator, i'll update the answer
                – FussinHussin
                8 mins ago















              This approach is soo gooad but I am getting error ts] The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<>
              – Programmer Man
              17 mins ago




              This approach is soo gooad but I am getting error ts] The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<>
              – Programmer Man
              17 mins ago












              the list I showd on my question actually can be logged from console.log(this.hits.value) or console.log(currentHits)
              – Programmer Man
              16 mins ago




              the list I showd on my question actually can be logged from console.log(this.hits.value) or console.log(currentHits)
              – Programmer Man
              16 mins ago












              @ProgrammerMan it's probably a bad import from rxjs. If you are using rxjs 6, import distinctUntilChanged from 'rxjs/operators'
              – FussinHussin
              12 mins ago




              @ProgrammerMan it's probably a bad import from rxjs. If you are using rxjs 6, import distinctUntilChanged from 'rxjs/operators'
              – FussinHussin
              12 mins ago












              Thank you for checking I have changed the import as you said and now getting this Argument of type '(value: any) => any' is not assignable to parameter of type '(x: any, y: any) => boolean'. Type 'any' is not assignable to type 'boolean'.
              – Programmer Man
              10 mins ago




              Thank you for checking I have changed the import as you said and now getting this Argument of type '(value: any) => any' is not assignable to parameter of type '(x: any, y: any) => boolean'. Type 'any' is not assignable to type 'boolean'.
              – Programmer Man
              10 mins ago












              @ProgrammerMan my apologies, actually you don't need to pass value in the operator, i'll update the answer
              – FussinHussin
              8 mins ago




              @ProgrammerMan my apologies, actually you don't need to pass value in the operator, i'll update the answer
              – FussinHussin
              8 mins ago










              up vote
              1
              down vote













              You can use following approach:



              Idea:



              • You can create your own data structure and have a hashMap to save values.

              • Since you have location data, you can use longitude|latitude as your key name as it will be unique.

              • Then expose some functions say, add that will check if value exists, override else add.

              • Also create a property, say value that would return the list of locations.

              Note: Above behavior can be achieved using Set as well. If you cannot use ES6 features, then this is one way that is extensible and easy.






              function MyList() 
              var locations = ;

              this.add = function(value) ');
              locations[key] = value;


              Object.defineProperty(this, 'value',
              get: function()
              return Object.keys(locations).map(function(key) return locations[key] )

              )


              var locations = new MyList();

              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.16, 451.23], name: 'test 2' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [100.12, 456.23], name: 'test 3' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.12, 400.23], name: 'test 4' );

              console.log(locations.value)





              Typescript version for more readability:





              interface ILocation 
              location: Array<number>
              [key: string]: any;


              interface IList
              [key: string]: ILocation


              class MyList
              private locations: IList = ;

              public add(value: ILocation) ');
              this.locations[key] = value;


              public get value(): Array<ILocation>
              return Object.keys(locations).map(function(key) return locations[key] )








              share






















              • This looks so nice can you translate it to typescript?? because when you say this.add where do you declare add?
                – Programmer Man
                6 mins ago










              • @ProgrammerMan I have added a typescript code sample. Its not runnable though. Hope it helps you!
                – Rajesh
                27 secs ago














              up vote
              1
              down vote













              You can use following approach:



              Idea:



              • You can create your own data structure and have a hashMap to save values.

              • Since you have location data, you can use longitude|latitude as your key name as it will be unique.

              • Then expose some functions say, add that will check if value exists, override else add.

              • Also create a property, say value that would return the list of locations.

              Note: Above behavior can be achieved using Set as well. If you cannot use ES6 features, then this is one way that is extensible and easy.






              function MyList() 
              var locations = ;

              this.add = function(value) ');
              locations[key] = value;


              Object.defineProperty(this, 'value',
              get: function()
              return Object.keys(locations).map(function(key) return locations[key] )

              )


              var locations = new MyList();

              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.16, 451.23], name: 'test 2' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [100.12, 456.23], name: 'test 3' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.12, 400.23], name: 'test 4' );

              console.log(locations.value)





              Typescript version for more readability:





              interface ILocation 
              location: Array<number>
              [key: string]: any;


              interface IList
              [key: string]: ILocation


              class MyList
              private locations: IList = ;

              public add(value: ILocation) ');
              this.locations[key] = value;


              public get value(): Array<ILocation>
              return Object.keys(locations).map(function(key) return locations[key] )








              share






















              • This looks so nice can you translate it to typescript?? because when you say this.add where do you declare add?
                – Programmer Man
                6 mins ago










              • @ProgrammerMan I have added a typescript code sample. Its not runnable though. Hope it helps you!
                – Rajesh
                27 secs ago












              up vote
              1
              down vote










              up vote
              1
              down vote









              You can use following approach:



              Idea:



              • You can create your own data structure and have a hashMap to save values.

              • Since you have location data, you can use longitude|latitude as your key name as it will be unique.

              • Then expose some functions say, add that will check if value exists, override else add.

              • Also create a property, say value that would return the list of locations.

              Note: Above behavior can be achieved using Set as well. If you cannot use ES6 features, then this is one way that is extensible and easy.






              function MyList() 
              var locations = ;

              this.add = function(value) ');
              locations[key] = value;


              Object.defineProperty(this, 'value',
              get: function()
              return Object.keys(locations).map(function(key) return locations[key] )

              )


              var locations = new MyList();

              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.16, 451.23], name: 'test 2' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [100.12, 456.23], name: 'test 3' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.12, 400.23], name: 'test 4' );

              console.log(locations.value)





              Typescript version for more readability:





              interface ILocation 
              location: Array<number>
              [key: string]: any;


              interface IList
              [key: string]: ILocation


              class MyList
              private locations: IList = ;

              public add(value: ILocation) ');
              this.locations[key] = value;


              public get value(): Array<ILocation>
              return Object.keys(locations).map(function(key) return locations[key] )








              share














              You can use following approach:



              Idea:



              • You can create your own data structure and have a hashMap to save values.

              • Since you have location data, you can use longitude|latitude as your key name as it will be unique.

              • Then expose some functions say, add that will check if value exists, override else add.

              • Also create a property, say value that would return the list of locations.

              Note: Above behavior can be achieved using Set as well. If you cannot use ES6 features, then this is one way that is extensible and easy.






              function MyList() 
              var locations = ;

              this.add = function(value) ');
              locations[key] = value;


              Object.defineProperty(this, 'value',
              get: function()
              return Object.keys(locations).map(function(key) return locations[key] )

              )


              var locations = new MyList();

              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.16, 451.23], name: 'test 2' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [100.12, 456.23], name: 'test 3' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.12, 400.23], name: 'test 4' );

              console.log(locations.value)





              Typescript version for more readability:





              interface ILocation 
              location: Array<number>
              [key: string]: any;


              interface IList
              [key: string]: ILocation


              class MyList
              private locations: IList = ;

              public add(value: ILocation) ');
              this.locations[key] = value;


              public get value(): Array<ILocation>
              return Object.keys(locations).map(function(key) return locations[key] )









              function MyList() 
              var locations = ;

              this.add = function(value) ');
              locations[key] = value;


              Object.defineProperty(this, 'value',
              get: function()
              return Object.keys(locations).map(function(key) return locations[key] )

              )


              var locations = new MyList();

              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.16, 451.23], name: 'test 2' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [100.12, 456.23], name: 'test 3' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.12, 400.23], name: 'test 4' );

              console.log(locations.value)





              function MyList() 
              var locations = ;

              this.add = function(value) ');
              locations[key] = value;


              Object.defineProperty(this, 'value',
              get: function()
              return Object.keys(locations).map(function(key) return locations[key] )

              )


              var locations = new MyList();

              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.16, 451.23], name: 'test 2' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [100.12, 456.23], name: 'test 3' );
              locations.add(location: [123.12, 456.23], name: 'test 1' );
              locations.add(location: [123.12, 400.23], name: 'test 4' );

              console.log(locations.value)





              share













              share


              share








              edited 1 min ago

























              answered 9 mins ago









              Rajesh

              15.3k42247




              15.3k42247











              • This looks so nice can you translate it to typescript?? because when you say this.add where do you declare add?
                – Programmer Man
                6 mins ago










              • @ProgrammerMan I have added a typescript code sample. Its not runnable though. Hope it helps you!
                – Rajesh
                27 secs ago
















              • This looks so nice can you translate it to typescript?? because when you say this.add where do you declare add?
                – Programmer Man
                6 mins ago










              • @ProgrammerMan I have added a typescript code sample. Its not runnable though. Hope it helps you!
                – Rajesh
                27 secs ago















              This looks so nice can you translate it to typescript?? because when you say this.add where do you declare add?
              – Programmer Man
              6 mins ago




              This looks so nice can you translate it to typescript?? because when you say this.add where do you declare add?
              – Programmer Man
              6 mins ago












              @ProgrammerMan I have added a typescript code sample. Its not runnable though. Hope it helps you!
              – Rajesh
              27 secs ago




              @ProgrammerMan I have added a typescript code sample. Its not runnable though. Hope it helps you!
              – Rajesh
              27 secs ago










              up vote
              0
              down vote













              Perhaps you would want to use a library such as lodash which has a wide set of functions regarding all types of collections.



              let newArr = _.uniqWith(myArr, _.isEqual);


              uniqWith with the help of isEqual can get what you want.



              Here is fiddle to that solution






              share|improve this answer
























                up vote
                0
                down vote













                Perhaps you would want to use a library such as lodash which has a wide set of functions regarding all types of collections.



                let newArr = _.uniqWith(myArr, _.isEqual);


                uniqWith with the help of isEqual can get what you want.



                Here is fiddle to that solution






                share|improve this answer






















                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  Perhaps you would want to use a library such as lodash which has a wide set of functions regarding all types of collections.



                  let newArr = _.uniqWith(myArr, _.isEqual);


                  uniqWith with the help of isEqual can get what you want.



                  Here is fiddle to that solution






                  share|improve this answer












                  Perhaps you would want to use a library such as lodash which has a wide set of functions regarding all types of collections.



                  let newArr = _.uniqWith(myArr, _.isEqual);


                  uniqWith with the help of isEqual can get what you want.



                  Here is fiddle to that solution







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 11 mins ago









                  malek yahyaoui

                  105




                  105



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52480479%2fremove-duplicates-from-an-array-of-geofire-objects%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Comments

                      Popular posts from this blog

                      What does second last employer means? [closed]

                      List of Gilmore Girls characters

                      Confectionery