简体   繁体   中英

How to check if array is unique on specific object property?

I have an array of objects:

var array1 = [
  {
    property1: 10,
    property2: "abc"
  }, 
  {
    property1: 11,
    property2: "def"
  },
  {
    property1: 10,
    property2: "ghi"
  }
];

Now what I want is this array will be said not unique as per value of property1 .

This means that this array contains 2 elements with property1=10 , so the array does not contain unique value of property1 .

To check this, I can use a for loop:

for (var i = 0; i < array1.length; i++) {
  var array2 = array1.slice(); // copy array
  array2.remove(array1[i]);
  var temppropety1 = array1[i].property1;
  for (var j = 0; j < array2.length; j++) {
    if (array2[J].property1==temppropety1) {
      return true;
    }
  }
}

But is there an easier way or a library to find this?

Here is a straightforward way to test for uniqueness on property1 . Loop through the objects in the outer array and add each object's property1 to a temp array if it is not already in that temp array. If a duplicate value is encountered, return false meaning property1 is not unique.

function isUnique(arr) {
   var tmpArr = [];
   for(var obj in arr) {
     if(tmpArr.indexOf(arr[obj].property1) < 0){ 
       tmpArr.push(arr[obj].property1);
     } else {
       return false; // Duplicate value for property1 found
     }
   }
   return true; // No duplicate values found for property1
}

Demo: http://jsbin.com/lohiqihipe/1/

I suggest that array can be quite big so I'd prefer not to copy it and just validate properties.

Also it is not an option to use map function of array because in this case you won't be able to break a cycle on first match:

var equals = function(array) {
    var co = {};
    var unique = true;
    for(var i = 0; i < array.length; i++) {
        var o = array[i];
        if (co[o.property1]) {
            unique = false;
            break;
        } else {
            co[o.property1] = true;
        }
    }
    return unique;
};

You can convert your array to flat structure:

array1.map(function(item) { return item.property1; });

and now your problem simplify to check duplicates in simple array

var array1 = ["a","b","b","c","d","e","f"];
var uniqueItems = [];
$.each(array1, function(i, el){
    if($.inArray(el, uniqueItems) === -1) uniqueItems.push(el);
});

References:

https://stackoverflow.com/a/840808/4772988

https://stackoverflow.com/a/9229932/4772988

You can use a couple of helpers to abstract it:

var uniqBy = function(f, xs) {
  var seen = []
  return xs.filter(function(x) {
    var fx = f(x)
    if (seen.indexOf(fx) > -1) return
    seen.push(fx)
    return true
  })
}

var dot = function(k) {
  return function(obj) {
    return obj[k]
  }
}

Then filter out duplicates by the property, and compare the length of the result to the original array. If they don't match, then they must not be unique:

var res = uniqBy(dot('property1'), array1)
var isUnique = array1.length === res.length

console.log(isUnique) // false

If you got only numbers or only strings to remove duplicates from, then you can improve performance by using an object instead of an array to keep track of elements seen so far.

First, you could reduce (aggregate) the objects by grouping them by the value of property1:

var grouped = array.reduce(function(grouped, item) {
    var propertyValue = item.property1;
    grouped[propertyValue] = (grouped[propertyValue] || 0) + 1;
    return grouped;
}, {});

Then you check that every key of the resulting object has a value of 1:

var result = Object.keys(grouped).every(function(key) {
    return grouped[key] === 1;
});

You can use lodash library to achieve this.

Here is the library documentation: https://lodash.com/docs/4.17.5#filter

Method:-

function isDuplicatesPresent(list, propertyName){
   return _.filter(list, function (value) { 
       return _.filter(list, function(innerValue){ reutrn innerValue[propertyName] === value[propertyName]}).length > 1;   
   }).length > 0;
}

Example:-

var users = [
  { user: 'barney', age: 36, active: true },
  { user: 'fred',  age: 40, active: false },
  { user: 'barney', age: 37, active: true}
];

let duplicates = _.filter(users, function (value) { 
    return _.filter(users, {user:value.user}).length > 1;   
});

Result:

console.log(duplicates)
> [
   {"user": "barney","age": 36,"active": true},
   {"user": "barney","age": 37,"active": true}
 ];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM