How to get first repeated object from an array of objects?

Viewed 134

I have an array of objects like this:

const result = [
  { ProductName: 'Orange', Origin: 'Italy' },
  { ProductName: 'Orange', Origin: 'Italy' },
  { ProductName: 'Lemon', Origin: 'Spain' },
  { ProductName: 'Avocado', Origin: 'Chile' }
];

// Expected output since there are duplicates:
const output = [{ ProductName: 'Orange', Origin: 'Italy' }]

Like shown above, there might be duplicates in the array (but it's not a must). That's why I'd like to:

  1. check if there are duplicates in the array
  2. if yes: create new array with only duplicates (show duplicate only 1x, even if there might be 2 or 3 duplicated in const result)
  3. if no: leave const result as is

By now, I tried to modify a code, which does the opposite: it finds unique (not duplicated) objects in the result-array. But I just can't get it work. Maybe it's just a wrong approach? Any help is appreciated!

const endresult = result
  .map(e => e.ProductName)
  .map((e, i, final) => final.indexOf(e) === i && i)
  .filter(e => result[e])
  .map(e => result[e]);
5 Answers

Here is a solution using reduce:

const result = [
  {ProductName: "Orange", Origin: "Italy"},
  {ProductName: "Orange", Origin: "Italy"},
  {ProductName: "Lemon",  Origin: "Spain"},
  {ProductName: "Avocado",Origin: "Chile"},
  {ProductName: "Orange", Origin: "Italy"}
];

function getDuplicatesOrAll(arr) {
  const duplicates = arr
    .reduce((acc, p, i) => {
      const isDuplicate = i !== result.findIndex(({ProductName}) => ProductName === p.ProductName);
      if (isDuplicate) {
        const wasAlreadyMet = acc.some(({ProductName}) => ProductName === p.ProductName);
        if (!wasAlreadyMet) {
          acc.push(p);
        }
      }
      return acc;
    }, []);
    
  return duplicates.length ? duplicates : arr;
}

console.log( getDuplicatesOrAll(result) );

Maybe easier to read using your method to work with names only:

 const result = [
  {ProductName: "Orange", Origin: "Italy"},
  {ProductName: "Orange", Origin: "Italy"},
  {ProductName: "Lemon",  Origin: "Spain"},
  {ProductName: "Avocado",Origin: "Chile"},
  {ProductName: "Orange", Origin: "Italy"}
];

function getDuplicatesOrAll(arr) {
  const duplicates = arr
    .map(({ProductName}) => ProductName)
    .reduce((acc, name, i, final) => {
      const isDuplicate = i !== final.indexOf(name);
      if (isDuplicate) {
        const wasAlreadyMet = acc.includes(name);
        if (!wasAlreadyMet) {
          acc.push(name);
        }
      }
      return acc;
    }, [])
    .map(name => result.find(({ProductName}) => ProductName === name));

  return duplicates.length ? duplicates : arr;
}

console.log( getDuplicatesOrAll(result) );

Can be accomplished using Array#filter and Array#some.

  • Filter the array using Array#filter and for each object check if that object is repeated.
  • For a object its repetition can be checked using Array#some.
  • If duplicates are found return that, else return the original array

const result = [
  { ProductName: 'Orange', Origin: 'Italy' },
  { ProductName: 'Orange', Origin: 'Italy' },
  { ProductName: 'Orange', Origin: 'Italy' },
  { ProductName: 'Orange', Origin: 'Italy' },
  { ProductName: 'Lemon', Origin: 'Spain' },
  { ProductName: 'Avocado', Origin: 'Chile' },
];

const getDups = (arr) => {
  const seen = new Set
  const dups = arr
    .filter((o1, i)=> arr.slice(i+1)
                          .some(o2 => o1.ProductName === o2.ProductName &&
                                      o1.Origin === o2.Origin)           
                       &&      
                      !arr.slice(0, i)
                         .some(o2 => o1.ProductName === o2.ProductName &&
                                      o1.Origin === o2.Origin));
  if(dups.length){
    return dups;
  }
  return arr;
}

console.log(getDups(result));

Make two object of unique items and duplicates, then check if duplicate exists make it array and return it.

const result = [
  { ProductName: 'Orange', Origin: 'Italy' },
  { ProductName: 'Orange', Origin: 'Italy' },
  { ProductName: 'Lemon', Origin: 'Spain' },
  { ProductName: 'Avocado', Origin: 'Chile' }
];

function duplicateFinder(array){
  const cache = {};
  const duplicates = {};
  let endResult = [];
  array.forEach(e=>{
    cache[e.Origin]?
      duplicates[e.Origin] = e:
      cache[e.Origin] = true;
  })
  Object.keys(duplicates).forEach(e => {
      endResult.push(duplicates[e])
  })
  return endResult.length ? endResult : array;
}

console.log(duplicateFinder(result))

You could do it using Array.prototype.sort() and Array.prototype.filter() method.

  • First, sort the array by ProductName.
  • Then use filter method for duplicates.
  • At last, if no duplicate is found then return the original array; otherwise, filtered duplicate result.

const result = [
  { ProductName: 'Orange', Origin: 'Italy' },
  { ProductName: 'Orange', Origin: 'Italy' },
  { ProductName: 'Lemon', Origin: 'Spain' },
  { ProductName: 'Avocado', Origin: 'Chile' },
];
let ret = result
  .sort((x, y) => x.ProductName.localeCompare(y.ProductName))
  .filter((x, i, a) => i > 0 && x.ProductName === a[i - 1].ProductName);
if (!ret.length) ret = result;
console.log(ret);

const result=[{ProductName:"Orange",Origin:"Italy"},{ProductName:"Orange",Origin:"Italy"},{ProductName:"Lemon",Origin:"Spain"},{ProductName:"Avocado",Origin:"Chile"}];

const findDuplicates = (arr)  => { 
    let result =[]
    arr.forEach((e,i) => {
        let slice = arr.slice(i+1)
        let dupl = slice.find(n => (n.ProductName === e.ProductName) && (n.Origin === e.Origin))
        if (dupl){
             if(!result.find(n => (n.ProductName === dupl.ProductName) && (n.Origin === dupl.Origin))){
            result.push(dupl)
            }
        }    
    })
    return result
}

console.log(findDuplicates(result))

Related