0

I want to get all objects with the same id, into a new array. In below data, first object with id: 1 is repeated at 3rd and 5th position, so I need to store 1st, 3rd and 5th position object into new array. Same thing if more id is repeated in data

Data:

const data = [
  { id: 1, file: 'test1.xlsx' },
  { id: 3, file: 'test1.xlsx' },
  { id: 1, file: 'test2.xlsx' },
  { id: 5, file: 'test2.xlsx' },
  { id: 1, file: 'test3.xlsx' },
  { id: 7, file: 'test3.xlsx' },
  { id: 8, file: 'test4.xlsx' },
  { id: 9, file: 'test4.xlsx' },
  { id: 9, file: 'test5.xlsx' },
  { id: 10, file: 'test5.xlsx' },
  { id: 9, file: 'test6.xlsx' },
]

My code:

// arr = data
// headerKey = 'id'
const getDuplicates = (arr, headerKey) => {
  return arr
    .map((el, i) => {
      return arr.find((element, index) => {
        if (i !== index && element[headerKey] === el[headerKey]) {
          return el
        }
      })
    })
    .filter((x) => x)
}

My incorrect output

[
  { id: 1, file: 'test2.xlsx' },
  { id: 1, file: 'test1.xlsx' },
  { id: 1, file: 'test1.xlsx' },
  { id: 9, file: 'test5.xlsx' },
  { id: 9, file: 'test4.xlsx' },
  { id: 9, file: 'test4.xlsx' }
]

expected output

[
  { id: 1, file: 'test1.xlsx' },
  { id: 1, file: 'test2.xlsx' },
  { id: 1, file: 'test3.xlsx' },
  { id: 9, file: 'test4.xlsx' },
  { id: 9, file: 'test5.xlsx' },
  { id: 9, file: 'test6.xlsx' }
]

In incorrect output section object with { id: 1, file: 'test1.xlsx' } is getting repeated 2 times which should not be the case and same thing with the other duplicate entry as well.

I think, I was able to figure that my current problem, and the reason why the output is incorrect is maybe because the find() method only returns first element.

I have searched solutions online, and many people have recommended to use reduce, or filter method but I'm not able to figure out how to implement it.

2 Answers 2

1

We can achieve the expected output by using Object.values, Array.reduce and finally checking the length of the accumulated array to get the duplicated id's with respective files like below.

const data = [{id:1,file:'test1.xlsx'},{id:3,file:'test1.xlsx'},{id:1,file:'test2.xlsx'},{id:5,file:'test2.xlsx'},{id:1,file:'test3.xlsx'},{id:7,file:'test3.xlsx'},{id:8,file:'test4.xlsx'},{id:9,file:'test4.xlsx'},{id:9,file:'test5.xlsx'},{id:10,file:'test5.xlsx'},{id:9,file:'test6.xlsx'}];

const findDuplicates = (data) => {
  const output = [];
  Object.values(data.reduce((res, obj) => {
    let key = obj.id;
    res[key] = [...(res[key] || []), {...obj}]
    return res;
  }, {})).forEach(arr => {
    if(arr.length > 1) {
      output.push(...arr);
    }
  });
  return output;
}

console.log(findDuplicates(data));
.as-console-wrapper {
  max-height: 100% !important;
}

Sign up to request clarification or add additional context in comments.

Comments

1

For less computational complexity, don't .find inside your .map - that's O(n ^ 2). I'd count up the number of occurrences of a given id on an object (or Map), then at the end, filter the values by the collections with at least 2 values in them:

const data = [
  { id: 1, file: 'test1.xlsx' },
  { id: 3, file: 'test1.xlsx' },
  { id: 1, file: 'test2.xlsx' },
  { id: 5, file: 'test2.xlsx' },
  { id: 1, file: 'test3.xlsx' },
  { id: 7, file: 'test3.xlsx' },
  { id: 8, file: 'test4.xlsx' },
  { id: 9, file: 'test4.xlsx' },
  { id: 9, file: 'test5.xlsx' },
  { id: 10, file: 'test5.xlsx' },
  { id: 9, file: 'test6.xlsx' },
]

// arr = data
// headerKey = 'id'
const getDuplicates = (arr, headerKey) => {
  const objsByHeader = {};
  for (const obj of arr) {
    objsByHeader[obj[headerKey]] ??= [];
    objsByHeader[obj[headerKey]].push(obj);
  }
  return Object.values(objsByHeader)
    .filter(subarr => subarr.length >= 2)
    .flat();
}
console.log(getDuplicates(data, 'id'));

3 Comments

index.js:51 objsByHeader[obj[headerKey]] ??= [] ^ SyntaxError: Unexpected token '=' i'm getting this error, i would like to point out that I'm using nodejs,
??= is Logical nullish assignment, Which is compatible from nodejs v15.0.0 onwards.
@PawanKanhere If you can't use ??= then you can do if (!objsByHeader[obj[headerKey]]) objsByHeader[obj[headerKey]] = []

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.