skip to Main Content

I’ve looked a pile of answers to related questions, but haven’t found anything that directly handles this. Should be simple, but I’m drawing a blank.

If I have an array like this:

const items = [
{id: uuid-uuu, itemId: 110, nbr: 135, recordID: 222},
{id: uuid-www, itemId: 111, nbr: 134, recordID: 555},
{id: uuid-xxx, itemId: 111, nbr: 134, recordID: 555},
{id: uuid-yyy, itemId: 111, nbr: 134, recordID: 111},
{id: uuid-zzz, itemId: 112, nbr: 135, recordID: 222},
]

And I want to look at itemId, nbr, and recordID values, (but NOT id and other keys not included in this example) and find any objects where those are all the same, and return those unchanged duplicated objects (multiple) in a new array.

So in this case, I just want this as the result:

const duplicateItems = [
{id: uuid-www, itemId: 111, nbr: 134, recordID: 555},
{id: uuid-xxx, itemId: 111, nbr: 134, recordID: 555},
]

I don’t want duplicates removed, I don’t want only unique items – I only want the duplicate list.

Should I be using reduce, filter, Map, etc.?

Needs to be in plain JavaScript, but can use latest / ES6 functions.

2

Answers


  1. [NOTE: REQUIRES POLYFILLS]

    Could try something like this;

    const items = [
    {id: "uuid-uuu", itemId: 110, nbr: 135, recordID: 222},
    {id: "uuid-www", itemId: 111, nbr: 134, recordID: 555},
    {id: "uuid-xxx", itemId: 111, nbr: 134, recordID: 555},
    {id: "uuid-yyy", itemId: 111, nbr: 134, recordID: 111},
    {id: "uuid-zzz", itemId: 112, nbr: 135, recordID: 222},
    ];
    
    let duplicateValues = [...Map.groupBy(items, item  => {
            return `${item.itemId}|${item.nbr}|${item.recordID}`;
    }).entries()].filter(x => x[1].length > 1).map(x => x[1]).flat();
    
    console.log(keys);
    
    1. Group items by key (you can’t use an object with the composite key for group by since the comparison isn’t deep, so you can concatenate (the | is to divide the keys).
    2. Get the entries and convert to array so you can use ES6 methods
    3. Filter out groups with more than 1 value (contain duplicates)
    4. Map to the value (since you don’t need the key)
    5. Flatten the result to get all duplicates of matching any composite key in the same array

    https://jsfiddle.net/tk13nzhm/32/

    Login or Signup to reply.
  2. So you need to generate a key based off the items you want. Easiest way is just using reduce. Reduce holds an object. You create an array with your key. You push in the objects into that array. After you are done with loop, filter your array for dupes and make it one array with flat.

    const items = [
      {id: 'uuid-uuu', itemId: 110, nbr: 135, recordID: 222},
      {id: 'uuid-www', itemId: 111, nbr: 134, recordID: 555},
      {id: 'uuid-xxx', itemId: 111, nbr: 134, recordID: 555},
      {id: 'uuid-yyy', itemId: 111, nbr: 134, recordID: 111},
      {id: 'uuid-zzz', itemId: 112, nbr: 135, recordID: 222},
    ];
    
    const dupedItems = Object.values(items.reduce((acc, row) => {
        const {
          itemId,
          nbr,
          recordID
        } = row;
        // build up a key with the fields
        const key = `${itemId}*${nbr}*${recordID}`;
        // define an array or use the one that already exists
        acc[key] ??= [];
        // add the item to your array for this key
        acc[key].push(row)
        return acc;
      }, {})).filter(x => x.length > 1) // select only the arrays with more than one items
      .flat(); // reduce the 2D array into a 1D array
    
    console.log(dupedItems);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search