1

I'm trying to do a neat little function for filtering an array of objects so that only object with unique value of a certain property is returned. This function works fine when prop is just a plain property such as "email". But the function does not work when giving nested properties as argument, like "customer.email"

        var unique = function (arr, prop) {
            var found = [];
            return arr.filter(function (obj) {
                if (found.indexOf(obj[prop]) < 0) return found.push(obj[prop]);
            });
        };

        reminders = unique(reminders, 'customer.email');

Is there a elegant way to give nested properties as argument, or is this something that should be avoided?

Anders Östman
  • 3,702
  • 4
  • 26
  • 48
  • 1
    Possibly a duplicate of [Convert string in dot notation to get the object reference](http://stackoverflow.com/q/10934664/710446) – apsillers Jan 21 '15 at 15:25
  • 1
    @apsillers I'd say it's not an exact duplicate, but the information therein should be enough for the OP to alter his `unique` function – James Thorpe Jan 21 '15 at 15:26

2 Answers2

1

Instead of passing a property name, I would pass in a property function:

var unique = function (arr, prop) {
    var found = [];

    return arr.filter(function (obj) {
        var value  = prop(obj);
        var result = found.indexOf(value) < 0;
        if (result) found.push(value);
        return result;
    });
};

var reminders = unique(reminders, function (obj) {
    return obj.customer.email;
});

Hope that helps.

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • Creative! But i hid some more code into the function instead... That way I can invoke it in just one line: `reminders = unique(reminders, 'customer.email');`. Becomes more readable. – Anders Östman Jan 21 '15 at 16:23
0

other version

   var unique = function (arr, prop) {
        var found = [];
        return arr.filter(function (obj) {

           var i=0, currentProp;
            while (obj && (currentProp=(prop.split("."))[i++]) ) {
              obj=obj[currentProp];
            }

            if (found.indexOf(obj) < 0) return found.push(obj);
        });
    };

  var  reminders=[{customer : {email:'test'}},{customer : {email:'vlad'}},{customer : {email:'vlad'}}];
  reminders= unique(reminders, 'customer.email');
  console.log(reminders);

  var  reminders=[ {email:'test'}, {email:'vlad'}, {email:'vlad'}];
  reminders= unique(reminders, 'email');
  console.log(reminders);
Vladu Ionut
  • 8,075
  • 1
  • 19
  • 30