HUJ
HUJ

Reputation: 57

Javascript remove array objects with duplicate properties while keeping the latest occurance

I've searched a lot for this but couldn't find anything that match my requirement.

I want to remove all the duplicates but keeping the last entry not the first.

The array is already presorted I don't want to mess with sorting

So it looks like this :

[{
    name:"Joe",
    status:"foo1" },
  {
    name:"Joe",
    status:"foo2"},
  {
     name:"Vani",
    status:"foo5"
  }]

The expected output looks like:

  [{
    name:"Joe",
    status:"foo2"},
  {
     name:"Vani",
    status:"foo5"
  }]

I'd be thankful if someone can help me!

Upvotes: 1

Views: 1962

Answers (5)

You
You

Reputation: 28

// remove duplicate while preserve order
array.filter((row, i, arr) => arr.slice(0, i).findIndex((l) => l === row) === -1)
// change `l === row` to your own comparison logic

In your case:

const data = [
  {
    name:"Joe",
    status:"foo1"
  },
  {
    name:"Joe",
    status:"foo2"
  },
  {
    name:"Vani",
    status:"foo5"
  }
];

const duplicateRemoved = data
  .toReversed()
  .filter((row, i, arr) => arr.slice(0, i).findIndex((l) => l.name === row.name) === -1)
  .toReversed();

Upvotes: 0

Ryan Barker
Ryan Barker

Reputation: 1

The accepted answer doesn't actually keep the order, it amends the object at the initially found index

You could amend it to look like this:

const data = [
  { name:"Joe", status:"foo1" },
  { name:"Vani", status:"foo2" },
  { name:"Joe", status:"foo3" }
];

const removeDupes = (arr, map = new Map()) => {
  arr.forEach((o, i) => map.set(o.name, {...o, order: i}));

  return [...map.values()].sort((a, b) => a.order - b.order);
};

console.log(removeDupes(data));

Or perhaps do something more simple like:

const data = [
  { name:"Joe", status:"foo1" },
  { name:"Vani", status:"foo2" },
  { name:"Joe", status:"foo3" }
];

let newData = [];
data.forEach(x => {
  newData = newData.filter(y => y.name != x.name);
  newData.push(x);
});

console.log(newData);

I'll let someone else figure out a more performant solution...

Upvotes: 0

Praveenkumar Kalidass
Praveenkumar Kalidass

Reputation: 429

Try using simple forEach,

const arr = [{ name:"Joe", status:"foo1" }, { name:"Joe", status:"foo2"}, { 
    name:"Vani", status:"foo5" }];

let result = {};
arr.forEach((val) => { result[val.name] = val; });

console.log(Object.values(result));

Hope this helps...

Upvotes: 0

Mohammad Usman
Mohammad Usman

Reputation: 39322

You can make use of ES6 Map. As from Docs:

The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.

const data = [
  { name:"Joe", status:"foo1" },
  { name:"Joe", status:"foo2" },
  { name:"Vani", status:"foo5" }
];

const removeDupes = (arr, map = new Map()) => {
  arr.forEach(o => map.set(o.name, o));

  return [...map.values()];
};

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

Upvotes: 2

Code Maniac
Code Maniac

Reputation: 37755

You can simply use reduce

let arr = [{ name:"Joe", status:"foo1" }, { name:"Joe", status:"foo2"}, { name:"Vani", status:"foo5" }]

let op = arr.reduce((op,inp)=>{
  op[inp.name] = inp
  return op
},{})

console.log(Object.values(op))

Upvotes: 3

Related Questions