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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.