0
originaData = [
{id: 1, description: abc },
{id: 2, description: def }
{id: 1, description: ghi }
{id: 3, description: jkl }
{id: 2, description: mno }
{id: 4, description: pqr }
]

expected result
uniqueData = [
{id: 3, description: jkl },
{id: 4, description: pqr }
]

duplicateData = [
{id: 1, description: abc },
{id: 2, description: def },
{id: 1, description: ghi },
{id: 2, description: mno }
]

I have already tried lodash's uniqBy. But It does not give me the expected results as it doesnt remove all the duplicate occurrences.

4 Answers 4

1

You can do this using filter and find in vanilla javascript:

originaData.filter((o, index) => originaData.find((_o, _index) => o.id === _o.id && index !== _index))

The above will give you the duplicate data in your array.

To get an array without duplicate data just use ! in the function logic:

originaData.filter((o, index) => !originaData.find((_o, _index) => o.id === _o.id && index !== _index))

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

Comments

1

You could group by id and sort the grouped data by lengths of the array.

var data = [{ id: 1, description: 'abc' }, { id: 2, description: 'def' }, { id: 1, description: 'ghi' }, { id: 3, description: 'jkl' }, { id: 2, description: 'mno' }, { id: 4, description: 'pqr' }],
    [duplicate, unique] = Object
        .values(data.reduce((r, o) => ((r[o.id] = r[o.id] || []).push(o), r), {}))
        .reduce((r, a) => (r[+(a.length === 1)].push(...a), r), [[], []]);        

console.log(unique);
console.log(duplicate);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

0

You can achieve this in vanilla javascript by using the Array.reduce method. First group the data by id, then divide the groups into unique and duplicate arrays. If you a group has only one item, the item is unique, or if the group has more than one entry, the containing entries are duplicates.

const originialData = [
  {id: 1, description: 'abc' },
  {id: 2, description: 'def' },
  {id: 1, description: 'ghi' },
  {id: 3, description: 'jkl' },
  {id: 2, description: 'mno' },
  {id: 4, description: 'pqr' }
]

// Group data as an object by using the Array.reduce method.
const groupedById = originialData.reduce((groups, item) => {
  // if a group has not yet been created, default to empty array.
  if (!groups[item.id]) {
    groups[item.id] = [];
  }

  // push the entry into the group
  groups[item.id].push(item);

  return groups;
}, {});

// Get the group keys
const groupKeys = Object.keys(groupedById);

// Iterate the group keys, and divide into unique and duplicates array
const [unique, duplicates] = groupKeys.reduce(([uniq, dupl], id) => {
  // Get the current group
  const group = groupedById[id];

  // Select array depending on length
  if (group.length === 1) { // if length is 1, then the item is unique
    uniq = uniq.concat(group);
  } else { // else the containing items are duplicates.
    dupl = dupl.concat(group);
  }


  return [uniq, dupl];
}, [[], []])

console.log(unique)

Working example here: https://jsbin.com/sijidacile/edit?js,console

Comments

0

You could tally the ids in the array. Then partition your data based upon the id count.

function tally(iterable, fn = obj => obj) {
  const tally = new Map();
  for (const item of iterable) {
    const key = fn(item);
    if (!tally.has(key)) tally.set(key, 0);
    tally.set(key, tally.get(key) + 1);
  }
  return tally;
}

function partition(iterable, fn = obj => obj) {
  const truthy = [], falsy = [];
  for (const item of iterable) {
    (fn(item) ? truthy : falsy).push(item);
  }
  return [truthy, falsy];
}

const originaData = [{id:1,description:'abc'},{id:2,description:'def'},{id:1,description:'ghi'},{id:3,description:'jkl'},{id:2,description:'mno'},{id:4,description:'pqr'}];
const idCount = tally(originaData, obj => obj.id);
const [uniqueData, duplicateData] =
  partition(originaData, obj => idCount.get(obj.id) == 1);

console.log(uniqueData);
console.log(duplicateData);

If you only need one of the two (uniqueData or duplicateData), use filter instead.

Comments

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.