'Remove array duplicates by property javascript

I have a list of objects:

   [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}]

I need a simple way to filter out duplicates with regard to the name property, so:

 [{name: "bob", age: "14"}, {name: "sue", age: "21"}]

There seem to be quite a few array duplicate removal questions, but not any based on a property. It can ignore all other fields.



Solution 1:[1]

Iterate the array, place all name values in a hash and skip objects whose name is already in the hash:

filterBy = function(ary, prop) {
  var seen = {};
  return ary.filter(function(item) {
    var key = item[prop];
    if(seen[key] === 1)
      return false;
    seen[key] = 1;
    return true;
  });
}

// 
a = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}]

b = filterBy(a, 'name');

console.log(b);

ES6 version:

filterBy = function(ary, prop) {
  var seen = new Set();
  return ary.filter(item => !seen.has(item[prop]) && seen.add(item[prop]));
}

a = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}]

b = filterBy(a, 'name');

console.log(b);

Solution 2:[2]

You can do it with 2 for loops as follows. All you have to do is, keeping a result array and every time you insert into it, check whether the name attributes are equal.

function findDuplicate(){
  var array= [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}];

  var result=[];
  for(x in array){
    var found=false;
    for(y in result){
      if(result[y].name.localeCompare(array[x].name)==0){
        found=true;
      }
    }
    if(!found){
      result.push(array[x]);
    }
  }
  console.log(result);
}

Solution 3:[3]

You could do this with forEach and thisArg param.

var data = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}];
var result = [];

data.forEach(function(e) {
  if (!this[e.name]) {
    this[e.name] = e;
    result.push(this[e.name]);
  }
}, {});

console.log(result)

Or with forEach and map()

var data = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}], result =[];

data.forEach(function(e) {
  if(result.map(a => {return a.name}).indexOf(e.name) == -1 ) result.push(e);
});

console.log(result)

Solution 4:[4]

You could use Array#filter and a this object for marking, if the same name is already filtered.

var array = [{ name: "bob", age: "14" }, { name: "bob", age: "16" }, { name: "sue", age: "21" }],
    filtered = array.filter(function (a) {
        if (!this[a.name]) {
            this[a.name] = true;
            return true;
        }
    }, Object.create(null));

console.log(filtered);

Solution 5:[5]

For the straightforward comparison in the Q., there are some good answers here. If you want to provide a custom comparison function that will work on e.g. object values, or that uses a RegExp, then take a look at the following.

var dedupwhen = function(fn, list){
    if(list[0] === undefined){
        return [];
    }
    // Join the first item to the remainder that has had the first
    // item filtered out (according to fn) and then been
    // deduplicated itself.
    return [list[0]].concat(dedupwhen(fn, list.slice(1).filter(function(item){
        return !fn(list[0], item);
    })));
};

var similarname = function(x,y){
    return RegExp('^' + x.name + '$', 'i').test(y.name);
};

var list = [
    {name: 'Sue', age: 44},
    {name: 'Bob', age: "14"},
    {name: 'bob', age: "16"},
    {name: 'sue', age: "21"}
];
console.log(dedupwhen(similarname, list));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 georg
Solution 2
Solution 3
Solution 4
Solution 5