Glory Raj
Glory Raj

Reputation: 17691

Removing duplicates with in an object array using angular 4

I have an array with below list of items as shown in image , I would like to remove the duplicates
[L7-LO, %L7-LO] from that array.

Array with repetitions
I have tried with the following conditions:

Scenario 1 :

this.formulalist.filter((el, i, a) => i == a.indexOf(el))

Scenario 2:

Observable.merge(this.formulalist).distinct((x) => x.Value)
          .subscribe(y => {
       this.formulalist.push(y)
   });

Scenario 3:

this.formulalist.forEach((item, index) => {
        if (index !== this.formulalist.findIndex(i => i.Value == item.Value)) 
        {
            this.formulalist.splice(index, 1);
        }

    });

None of the three scenarios above were able to remove the duplicates from that array. Could any one please help on this query?

Upvotes: 6

Views: 29854

Answers (7)

Keyur Patel
Keyur Patel

Reputation: 67

// user reduce method to remove duplicates from object array , very easily

  this.formulalist= this.formulalist.reduce((a, b) => {
      if (!a.find(data => data.name === b.name)) {
        a.push(b);
      }
      return a;
    }, []);

// o/p = in formulalist you will find only unique values

Upvotes: 2

Ashish Ranjan
Ashish Ranjan

Reputation: 12960

Try populating a new array without duplicates. Assign the new array later to formulalist.

newArr = []
this.formulalist.forEach((item, index) => {
    if (this.newArr.findIndex(i => i.Value == item.Value) === -1) 
    {
        this.newArr.push(item)
    }

});
this.formulalist = this.newArr

EDIT

Looking at the answer above, the solution seems so outdated. A better approach would have been to use an Array.filter() than a Array.forEach().

But, having a better solution would be nice, now when I see this question, I feel findIndex() not to be a good approach because of the extra traversal.

I may have a Set and store the values in the Set on which I want to filter, If the Set has those entries, I would skip those elements from the array.

Or a nicer approach is the one that is used by Akitha_MJ, very concise. One loop for the array length, an Object(Map) in the loop with keys being the value on which we want to remove duplicates and the values being the full Object(Array element) itself. On the repetition of the element in the loop, the element would be simply replaced in the Map. Later just take out the values from the Map.

Upvotes: 5

Akitha_MJ
Akitha_MJ

Reputation: 4294

const result = Array.from(this.item.reduce((m, t) => m.set(t.name, t), new Map()).values());

Hope this works !!

Upvotes: 3

Dasha Ermolova
Dasha Ermolova

Reputation: 554

Filtering for unique values is much faster with assigning values to some object properties - there not will be duplicates. This approach gets better and better with every +1 member of initial array, because looping will be causing fast algorithm complications

let arr = [
  {value: 'L7-LO', name: 'L7-LO'},
  {value: '%L7-LO', name: '%L7-LO'},
  {value: 'L7-LO', name: 'L7-LO'},
  {value: '%L7-LO', name: '%L7-LO'},
  {value: 'L7-L3', name: 'L7-L3'},
  {value: '%L7-L3', name: '%L7-L3'},
  {value: 'LO-L3', name: 'LO-L3'},
  {value: '%LO-L3', name: '%LO-L3'}
];
let obj = {};

const unique = () => {
  let result = [];
  
  arr.forEach((item, i) => {
    obj[item['value']] = i;
  });
  
  for (let key in obj) {
    let index = obj[key];
    result.push(arr[index])
  }
  
  return result;
}

arr = unique(); // for example; 

console.log(arr);

Upvotes: 0

Piyush Khanna
Piyush Khanna

Reputation: 306

if you are working using ES6 and up, basic JS using map and filter functions makes it easy.

var array = [{value:"a"},{value:"b"},{value:"c"},{value:"a"},{value:"c"},{value:"d"}];

console.log(array.filter((obj, pos, arr) => {
    return arr.map(mapObj => mapObj["value"]).indexOf(obj["value"]) === pos;
}));

Upvotes: 0

quirimmo
quirimmo

Reputation: 9988

Use a reducer returning a new array of the unique objects:

const input = [{
    value: 'L7-LO',
    name: 'L7-LO'
  },
  {
    value: '%L7-LO',
    name: '%L7-LO'
  },
  {
    value: 'L7-LO',
    name: 'L7-LO'
  },
  {
    value: '%L7-LO',
    name: '%L7-LO'
  },
  {
    value: 'L7-L3',
    name: 'L7-L3'
  },
  {
    value: '%L7-L3',
    name: '%L7-L3'
  },
  {
    value: 'LO-L3',
    name: 'LO-L3'
  },
  {
    value: '%LO-L3',
    name: '%LO-L3'
  }
];
console.log(input.reduce((acc, val) => {
  if (!acc.find(el => el.value === val.value)) {
    acc.push(val);
  }
  return acc;
}, []));

Upvotes: 0

imperezivan
imperezivan

Reputation: 781

angular is not necessary use vanillajs filter the elements with only one occurrence and add to the new list the first occurrence

let newFormulalist =  formulalist.filter((v,i) => formulalist.findIndex(item => item.value == v.value) === i);

Upvotes: 6

Related Questions