4

I am trying to create an array with objects holding day and time. I am looping over a source where there may be duplicates so I want to check each time that I don't already have the current day and time stored.

However, I keep ending up with duplicates. So I figure the array.indexOf maybe doesn't work with objects?

    movies.forEach(function(movie){
        if (days.indexOf(movie.day) !== -1) { //if the movie's day exists in our array of available days...
            possibleMovies.push(movie);

            //create a day/time object for this movie
            dt = {day: movie.day, time: movie.time};

            //unless we already have this day and time stored away, do so
            if (possibleTimes.indexOf(dt) === -1) {
                possibleTimes.push(dt);
            }

        }
    });

What possibleTimes holds after the loop is done:

[ { day: '01', time: '18:00' },
  { day: '01', time: '16:00' },
  { day: '01', time: '18:00' },
  { day: '01', time: '16:00' } ]

I would expect line three and four not to be there...

---------- UPDATE ----------

I changed

dt = {day: movie.day, time: movie.time};

into this

dt = JSON.stringify({day: movie.day, time: movie.time});

and it works as expected. just need to JSON.parse once I retrieve the data.

4
  • 3
    Objects are compared by references, not their contents. Commented Feb 4, 2016 at 22:34
  • 1
    Oh, thanks. I just tried stringifying it and then it worked as expected, and you just explained why =) Commented Feb 4, 2016 at 22:35
  • You should take a look at www.lodash.com Commented Feb 4, 2016 at 22:36
  • @MattWelander Careful with stringifying often. That's a relatively expensive operation, where you might just want to iterate and test filtering properties instead. Consider running some performance tests, if performance is critical. Commented Feb 4, 2016 at 22:39

3 Answers 3

4

According to MDN:

indexOf() compares searchElement to elements of the Array using strict equality (the same method used by the ===, or triple-equals, operator).

That's why that possibleTimes.indexOf always results in -1.

Sign up to request clarification or add additional context in comments.

Comments

4

Two objects are considered equal if they point to the same location.

var obj1 = { x: 100 };
var obj2 = obj1;
console.log( obj1===obj2 );     //  outputs true

var obj1 = { x: 100 };
var obj2 = { x: 100 };
console.log( obj1===obj2 );     //  outputs false

You could use JSON.stringify to convert each object to string and then compare them. Keep in mind that the orders of properties must match.

console.log( JSON.stringify( obj1 ) === JSON.stringify( obj2) );    //outputs true

Comments

1

If you're open to using Ramda, it becomes super easy:

let a = [
  { day: '01', time: '18:00' },
  { day: '01', time: '16:00' },
  { day: '01', time: '18:00' },
  { day: '01', time: '16:00' }
];

let b = R.uniq(a);
console.log(b);

http://jsbin.com/ligihexate/edit?js,console

3 Comments

"it becomes super easy" --- your code does not produce the correct result though.
@zerkms I assume you didn't actually read the code I posted and just ran the JS Bin. It must have been modified when I started playing with the ES6 Set object. The two lines that are commented...uncomment them.
I've updated the JS Bin example. Sorry for the confusion. I haven't been using it for too long.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.