1

Why spread is not removing the duplication from the Items?

I am using spread to merge two variables resultA and resultB. There are two duplicated Id (222) in DataA and DataB which should be removed when using spread. Why it did not happen and how to solve this?

const DataA = [
  { Id: 111, Name: 'A'  },
  { Id: 222, Name: 'B'  },
  { Id: 333, Name: 'C'  }
]

const DataB = [
  { Id: 999, Name: 'A'  },
  { Id: 222, Name: 'B'  },
  { Id: 444, Name: 'C'  }
]

let resultA = (DataA || []).map(item => item.Id);
let resultB = (DataB || []).map(item => item.Id);

const items = [
  ...resultA,
  ...resultB,
]

const mapping = {
  Total: items.length,
  Items: items.map(item => { return { Id: item }})
}

console.log(mapping);

Expected Result:

{ Total: 5,
  Items:
   [ { Id: 111 },
     { Id: 222 },
     { Id: 333 },
     { Id: 999 },
     { Id: 444 } ] 
}
user88432
  • 397
  • 1
  • 4
  • 13
  • 5
    Why would the spread syntax remove duplicates? – VLAZ Feb 26 '20 at 21:30
  • I thought it does, how would you rewrite this? – user88432 Feb 26 '20 at 21:32
  • const items = [ ...new Set(resultA), ...new Set(resultB), ] – porsekin Feb 26 '20 at 21:32
  • All it does is unpack an array as individual elements. So if you need [a Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set), as just mentioned: "use a Set" =) – Mike 'Pomax' Kamermans Feb 26 '20 at 21:32
  • Spread literally just spreads array values. It doesn't de-dup. No idea where you got that idea from. – zfrisch Feb 26 '20 at 21:33
  • I'd use a Set to store the IDs, since then they'd be unique. Then map the Set to items afterwards as you do here. [Suggestions on how to do this (and other techiques) here](https://stackoverflow.com/questions/11246758/how-to-get-unique-values-in-an-array) – VLAZ Feb 26 '20 at 21:33
  • Didn't you ask almost the same question about 15 minutes ago? – Barmar Feb 26 '20 at 21:38
  • 1
    @zfrisch He's thinking of when you spread objects rather than arrays. – Barmar Feb 26 '20 at 21:39

2 Answers2

0

The spread syntax on arrays doesn't remove duplicates. To get the result you wanted, Add a line items = [...new Set(items)] after items

const DataA = [
  { Id: 111, Name: 'A'  },
  { Id: 222, Name: 'B'  },
  { Id: 333, Name: 'C'  }
]

const DataB = [
  { Id: 999, Name: 'A'  },
  { Id: 222, Name: 'B'  },
  { Id: 444, Name: 'C'  }
]

let resultA = (DataA || []).map(item => item.Id);
let resultB = (DataB || []).map(item => item.Id);

let items = [
  ...resultA,
  ...resultB,
]

items = [...new Set(items)] // this will remove duplicates 

const mapping = {
  Total: items.length,
  Items: items.map(item => { return { Id: item }})
}

console.log(mapping);
Henok Teklu
  • 528
  • 3
  • 9
0

I don't know where you've read that spread removes duplicates, but it does not. Luckily, there are a number of simple ways to achieve this - below is one option that involves very little modification to your code. Simply wrap the array containing items from the 2 spread arrays in a Set constructor (since I see you're already coding to the ES6 spec).

From MDN:

Set objects are collections of values. You can iterate through the elements of a set in insertion order. A value in the Set may only occur once; it is unique in the Set's collection.

Finally, you can simply wrap the Set in Array.from to get back to an array (among other ways to do this).

const DataA = [{
    Id: 111,
    Name: 'A'
  },
  {
    Id: 222,
    Name: 'B'
  },
  {
    Id: 333,
    Name: 'C'
  }
]

const DataB = [{
    Id: 999,
    Name: 'A'
  },
  {
    Id: 222,
    Name: 'B'
  },
  {
    Id: 444,
    Name: 'C'
  }
]

let resultA = (DataA || []).map(item => item.Id);
let resultB = (DataB || []).map(item => item.Id);

const items = Array.from(new Set([
  ...resultA,
  ...resultB,
]));

const mapping = {
  Total: items.length,
  Items: items.map(item => {
    return {
      Id: item
    }
  })
}

console.log(mapping);
Tom O.
  • 5,730
  • 2
  • 21
  • 35