1

I have an array with objects and I need to remove duplicates based on the data-itemid prop.

This is my code:

const ListItemsUnique = []
ListItems.map(item => {
  if (ListItemsUnique.indexOf(item.props['data-itemid']) === -1) {
    ListItemsUnique.push(item)
  }
});

It returns exactly the same array as before, what am I doing wrong?

Chris
  • 57,622
  • 19
  • 111
  • 137
Michaela
  • 268
  • 2
  • 4
  • 14

3 Answers3

2

if you are using ES6, Try this,

const ListItemsUnique = [...new Set(ListItems.map(item => item.props['data-itemid']))];

EDIT 1:

let data = [
  {
    name: 'John',
    "data-itemid": 2
  },
  {
    name: 'Doe',
    "data-itemid": 1
  },
  {
    name: 'James',
    "data-itemid": 1
  },
  {
    name: 'Clerk',
    "data-itemid": 2
  }
];

// Use Map (ES6) to retain only unique elements
let map = new Map();
for (element of data) {
  map.set(element["data-itemid"], element);
}


var filteredData = [];
map.forEach( (value) => {
  filteredData.push(value);
});

console.log(filteredData,"filteredData");

DEMO: https://codepen.io/vedp/pen/RpmVvx?editors=0011

Ved
  • 11,837
  • 5
  • 42
  • 60
1

The easiest and cleanest way would be to use a temporary set to store which items you have previously returned to your array, while you're mapping through it. Like so:

let tempSet = new Set();
const ListItemsUnique = ListItems.filter(item => {
  if(!tempSet.has(item.props['data-itemid'])) {
      tempSet.add(item.props['data-itemid']);
    return item;
  }
});

then do your mapping as usual.


Demo

let ListItems = [
  {name: "A", props: {"data-itemid": 1}},
  {name: "B", props: {"data-itemid": 1}},
  {name: "C", props: {"data-itemid": 2}},
  {name: "D", props: {"data-itemid": 3}},
  {name: "E", props: {"data-itemid": 3}},
];  //mock data

let tempSet = new Set();
const ListItemsUnique = ListItems.filter(item => {
  if(!tempSet.has(item.props['data-itemid'])) {
    tempSet.add(item.props['data-itemid']);
    return item;
  }
})

console.log(ListItemsUnique.map(item => item.name));  //Items "B" and "E" are skipped

By the way, Set is great for when dealing with, or wanting to achieve, a unique collection of data. Have a read on the MDN for more info on Set.

Here's a snippet from the docs:

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.

Community
  • 1
  • 1
Chris
  • 57,622
  • 19
  • 111
  • 137
1

you can also use immutable js or JSON.stringify (depending on how deep ur objects are or how deep you want to compare ;) )

  1. use immutablejs - fromJS + compare
  2. use JSON.stringify

Example for JSON.stringify

const ListItems = [{a: 'a'}, {a: 'b'}, {a: 'a'}];

let ListItemsUnique = [];
let stringList = [];

ListItems.forEach(item => {
    const itemString = JSON.stringify(item);
    if (stringList.indexOf(itemString) === -1) {
        ListItemsUnique.push(item);
    }
    stringList.push(itemString);
})

console.log(ListItemsUnique);
MarcelD
  • 393
  • 1
  • 9