Find duplicate values in objects with Javascript

2020-03-20 20:46发布

问题:

I've been trying to work out a problem I'm having. I have an array with objects in it, like this:

var array = [
  {
    name: "Steven Smith",
    Country: "England",
    Age: 35
  },
  {
    name: "Hannah Reed",
    Country: "Scottland",
    Age: 23
  },
  {
    name: "Steven Smith",
    Country: "England",
    Age: 35
  },
  {
    name: "Robert Landley",
    Country: "England",
    Age: 84
  },
  {
    name: "Steven Smith",
    Country: "England",
    Age: 35
  },
  {
    name: "Robert Landley",
    Country: "England",
    Age: 84
  }
];

I want to get the objects that have duplicate values in them and based on what values to search for. I.e , I want to get the object that has a duplicate value "name" and "age" but nog "country" so I will end up with:

[
  {
    name: "Steven Smith",
    Country: "England",
    Age: 35
  },
  {
    name: "Steven Smith",
    Country: "England",
    Age: 35
  },
  {
    name: "Robert Landley",
    Country: "England",
    Age: 84
  },
  {
    name: "Steven Smith",
    Country: "England",
    Age: 35
  },
  {
    name: "Robert Landley",
    Country: "England",
    Age: 84
  }
];

If been trying to do

array.forEach(function(name, age){
  if(array.name == name || array.age == age){
    console.log(the result)
}
})

But that only checks if the values of the object is equal to them self.

Can anybody help me?

回答1:

You can use 2 reduce. The first one is to group the array. The second one is to include only the group with more than 1 elements.

var array = [{"name":"Steven Smith","Country":"England","Age":35},{"name":"Hannah Reed","Country":"Scottland","Age":23},{"name":"Steven Smith","Country":"England","Age":35},{"name":"Robert Landley","Country":"England","Age":84},{"name":"Steven Smith","Country":"England","Age":35},{"name":"Robert Landley","Country":"England","Age":84}]

var result = Object.values(array.reduce((c, v) => {
  let k = v.name + '-' + v.Age;
  c[k] = c[k] || [];
  c[k].push(v);
  return c;
}, {})).reduce((c, v) => v.length > 1 ? c.concat(v) : c, []);

console.log(result);



回答2:

Quick answer I came up now:

   
let result = [];

for(let item of array)
{
    for(let checkingItem of array)
    {
      if(array.indexOf(item) != array.indexOf(checkingItem) &&
        (item.name == checkingItem.name || item.Age == checkingItem.Age))
      {
        if(result.indexOf(checkingItem) == -1)
        {
          result.push(checkingItem);
        }

      }
   }
}

console.log(result);



回答3:

Try below snippet. It loops array through it's own elements (inner loop). 1st if condition checks for same element (we do not want that in output), 2nd if does the required condition match to identify any duplicate object.

var array = [
	{
		name: "Steven Smith",
		Country: "England",
		Age: 35
	},
	{
		name: "Hannah Reed",
		Country: "Scottland",
		Age: 23
	},
	{
		name: "Steven Smith",
		Country: "England",
		Age: 35
	},
	{
		name: "Robert Landley",
		Country: "England",
		Age: 84
	},
	{
		name: "Steven Smith",
		Country: "England",
		Age: 35
	},
	{
		name: "Robert Landley",
		Country: "England",
		Age: 84
	}
];

for(let obj of array){
	for(let ele of array){
		if(obj==ele)
			continue;
		if(ele.name===obj.name && ele.age===obj.age){
			console.log(obj);
			break;
		}
	}
}



回答4:

Here's an alternative solution, which I will point out the

let array      = getData();                       // sets up data array
let duplicates = array.filter(duplicatesOnly);    // filter out duplicates

console.log( duplicates );                        // output to console



/* ============================================================================= */


// Returns true/false based on a duplicate object being found   
function duplicatesOnly(v1, i1, self) {
  let ndx = self.findIndex(function(v2, i2) {
    // make sure not looking at the same object (using index to verify)
    // use JSON.stringify for object comparison
    return (i1 != i2 && JSON.stringify(v1) == JSON.stringify(v2))
  })
  return i1 != ndx && ndx != -1
}


// Use function hoisting to place trivial code at the bottom of example
function getData() {
  return [{
      name: "Steven Smith",
      Country: "England",
      Age: 35
    },
    {
      name: "Hannah Reed",
      Country: "Scottland",
      Age: 23
    },
    {
      name: "Steven Smith",
      Country: "England",
      Age: 35
    },
    {
      name: "Robert Landley",
      Country: "England",
      Age: 84
    },
    {
      name: "Steven Smith",
      Country: "England",
      Age: 35
    },
    {
      name: "Robert Landley",
      Country: "England",
      Age: 84
    }
  ];
}

Benefits

  • Heart of code is 3 lines
  • Code is clear
  • Easy to maintain

Costs

  • Performance
    • JSON.stringify is being performed on two objects on each iteration (very expensive)
    • Complexity: O(N^2) -- the bigger the array, the slower it may become

Notes


  • JSON.stringify may create the string based on key order, so even if objects have the same keys/values, the order may be a factor when comparing the objects -- this could be seen as a benefit or a cost
  • This is an example of using filter and findIndex the concentration was not on making it efficient. It could be improved by using caching and performing JSON.stringify once, or avoiding it altogether with something more customized.