0

I would like to return a unique array where the room object is the same.

var input = [
  {
    position:{
      room: {
        name: 'WC',
        number: '001'
      }
    }
  },
  {
    position:{
      room: {
        name: 'WC',
        number: '001'
      }
    }
  },
  {
    position:{
      room: {
        name: 'RWC',
        number: '007'
      }
    }
  }
];

So this list would be:

var input = [
  {
    position:{
      room: {
        name: 'WC',
        number: '001'
      }
    }
  },
  {
    position:{
      room: {
        name: 'RWC',
        number: '007'
      }
    }
  }
];

I tried this:

  var distinctRooms = _.uniq(input, function(input){
    return input.position.room
  });

But it returns the entire list. Have not seen any example where you compare objects. Is this possible to do somehow with the _uniq?

Joe
  • 4,274
  • 32
  • 95
  • 175

4 Answers4

1

Room objects are different. If you consider rooms to be equal based on their numbers you can use

  var distinctRooms = _.uniq(input, function(input){
    return input.position.room.number;
  });
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
0

Maybe you should take a look at this answer where he iterates and creates an array with unique values.

Community
  • 1
  • 1
rafaelune
  • 59
  • 6
0

Using the _.isEqual() function that provides deep object comparison it is possible to create a function that applies it to an array of objects and create a mix-in from that function.

Algorithm:

  1. take the first element from the list (the head), store it in the result
  2. iterate the rest of the list (the tail), remove every element that .isEqual to the first element
  3. if the rest of the list is not empty, pass it to step 1, otherwise return the result

Code, implemented with a recursive approach:

_.mixin({
    deepUniq: (function () {
        var dedup = function (coll, result) {
            var head = _.first(coll),
                tail = _.reject(_.rest(coll), function (curr) {
                    return _.isEqual(curr, head);
                });

            result.push(head);
            return (tail.length) ? dedup(tail, result) : result;
        };
        return function (coll) {
            return dedup(coll, []);
        };
    })()
});

A word of warning: This approach has exponential running time, i.e. it will be increasingly slow for long lists of deeply nested objects. My advice would be to compare correctness and performance of different solutions.


Disclaimer: This solution is based on https://stackoverflow.com/a/19641747/

Community
  • 1
  • 1
Tomalak
  • 332,285
  • 67
  • 532
  • 628
-1

As long as you don't have circular structures, you can use JSON Stringify to make a deep comparison of every room attribute

_.uniq(input, function(input){
    return JSON.stringify(input.position.room)
  });
ffflabs
  • 17,166
  • 5
  • 51
  • 77