Remove Duplicate In Array Using Pure Javascript Or

2019-09-05 17:10发布

This question already has an answer here:

I seem to only find ways to remove duplicates from an array using other JS libraries but I'm looking to do it in pure JS or typescript since I'm working on an Angular project.

My problem is that I may get an array that has duplicate entries, such as this one:

data [0: {Id: 1, Definition: "House"},
      1: {Id: 1, Definition: "House"}]

And I want to filter it out so that I only get

data [0: {Id: 1, Definition: "House"}]

I've tried it using this method but I still get duplicate entries

let uniqueArray = data.filter(function(item, pos) {
    return data.indexOf(item) == pos;
})

3条回答
甜甜的少女心
2楼-- · 2019-09-05 17:39

If the ID is what determines identity, then you could use a Map or a plain Object to dedupe. Same IDs will take the same spot on the map, so you end up with unique objects (if the above assumptions about IDs hold).

let data = [{Id: 1, Definition: "House"}, {Id: 1, Definition: "House"}];
let idToObj = {};
data.forEach((o) => idToObj[o.Id] = o);
let uniqueArray = Object.values(idToObj);

EDIT: In case that you want the same but you may have objects with the same ID but differing in other fields, a Map comes in handy because it can take whole objects as keys:

let data = [{Id: 1, Definition: "House1"}, {Id: 1, Definition: "House2"}];
let map = new Map();
data.forEach((o) => map.set(o, true));
let uniqueArray = [...map.keys()];
查看更多
Rolldiameter
3楼-- · 2019-09-05 17:55

You can achieve what you want in this way:

You can check if the value is already there in your final array using 'some'

data = [{Id: 1, Definition: "House"}, {Id: 1, Definition: "House"}]

const finalOut = []
data.forEach((value) => {
    if (!finalOut.some(x=> (x.Id === value.Id || x.Definition === value.Definition))) 
   {
        finalOut.push(value)
    }
})

You can also achieve this by 'reduce' in clean and elegant way:

const finalOut2 = data.reduce((acc, cur) => acc.some(x=> (x.Id === cur.Id || x.Definition === cur.Definition)) ? acc : acc.concat(cur), [])

As suggested by @Ezequiel using some inside forEach or reduce making the time complexity of order of n square. For smaller sets of data using reduce and some is an elegant approach. But if you are dealing with arrays of very large length, you must avoid order of n square time complexity Here is one such approach with filter:

//Here storing every value of data is inside lookupObj after filtering it. 
//And checking if value is filtered based on if key of the value inside lookupObj

const lookupObj = {} 
const finalOut3 = data.filter(
    x => {
        const is_unique = !(lookupObj[`Id_${x.Id}`] || lookupObj[`Id_${x.Definition}`])
        lookupObj[`Id_${x.Id}`] = true
        lookupObj[`Id_${x.Definition}`] = true
        return is_unique
    }
)
查看更多
再贱就再见
4楼-- · 2019-09-05 17:56

You can use Id key of the object to get the unique object using array#reduce in an object accumulator and get all the object of this object using Object.values().

let data = [{Id: 1, Definition: "House"},{Id: 1, Definition: "House"}, {Id: 2, Definition: "House2"}, {Id: 2, Definition: "House2"}],
    result = Object.values(data.reduce((r, o) =>  {
      r[o.Id] = r[o.Id] || {...o};
      return r;
    },{}));
console.log(result);

查看更多
登录 后发表回答