0

I have a source list of objects of 4 properties with some duplicate values, want to select distinct objects of 2 properties without using a foreach loop.

Source list:

let Students=  [
 {Id: 1, Name: 'A', Class: 'I', Subject: 'Math'},
 {Id: 2, Name: 'B', Class: 'II', Subject: 'Bengali'},
 {Id: 1, Name: 'A', Class: 'I', Subject: 'Science'},
 {Id: 2, Name: 'B', Class: 'II', Subject: 'English'}
];

I want an output list like:

[
  {Id: 1, Name: 'A'},
  {Id: 2, Name: 'B'}
]
  • Take a look to [this](https://www.learnrxjs.io/operators/transformation/groupby.html). – dcg Jun 22 '19 at 04:41
  • Did any answer work for you? If yes do consider accepting/upvoting one [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers) – Nicholas K Jun 26 '19 at 13:51

6 Answers6

1

Since we're in the world of typescript, make use of the types provided by it. Create a class Student, this will be useful for easier management of your objects.

export class Student {
  Id: number;
  Name: string;
  Class?: string;
  Subject?: string;

  constructor(Id: number, Name: string) {
    this.Id = Id;
    this.Name = Name;
  }
}

Create an array to hold the distinct objects:

distinctStud: Student[] = [];

Now you may:

from(this.Students)
   .pipe(
      map(std => new Student(std.Id, std.Name)),
      distinct(x => x.Id && x.Name)
    )
   .subscribe(val => this.distinctStud.push(val));
Nicholas K
  • 14,118
  • 7
  • 25
  • 49
1

Simple Solution to return Distinct data for Object Array

this.studentOptions = this.students.filter((item, i, arr) => arr.findIndex((t) => t.Id=== item.Id) === i);

Dhruv Parekh
  • 156
  • 1
  • 5
0

Array.from(new Set(yourArray.map((item: any) => item.id)))

0

You can try this like newbie way

    let st=[];
Students.map((data)=>{
 let isExist=!!st.find((data2)=>{ 
 return data2.Id==data.Id});
if(!isExist)
  st.push(data);
});
Shahid Islam
  • 440
  • 3
  • 6
0

Using rxjs's map and distinct operators we can achieve this. Please check the code below

   var Students=  [
 {Id: 1, Name: 'A', Class: 'I', Subject: 'Math'},
 {Id: 2, Name: 'B', Class: 'II', Subject: 'Bengali'},
 {Id: 1, Name: 'A', Class: 'I', Subject: 'Science'},
 {Id: 2, Name: 'B', Class: 'II', Subject: 'English'}
];

  const sourceObj = from(Students);
  const mappedObj=sourceObj.pipe(map((x)=>{return {Id: x.Id, Name:x.Name}}));
  const distictObj = mappedObj.pipe(distinct((x)=>x.Id && x.Name));

  console.log(distictObj.subscribe(x=>console.log(x)));

Please check this StackBlitz.

Thanks.

Obaid
  • 2,115
  • 14
  • 13
0

This solution produces the result in the form you asked for. Objects need to be stringified before they get added to the Set, otherwise equal ones are not recognized (see https://stackoverflow.com/a/29759699/2358409).

const set = new Set(Students.map(s => JSON.stringify({ Id: s.Id, Name: s.Name })));
const identifiers = Array.from(set).map(i => JSON.parse(i)); 

If you want to avoid stringify, you can do the following.

const set = new Set(Students.map(s => s.Id + ';' + s.Name));
const identifiers = Array.from(set).map(i => ({ Id: i.split(';')[0], Name: i.split(';')[1] }));

The same can be done in a cleaner way using Map.

const map = new Map();
Students.map(s => map.set(s.Id, { Id: s.Id, Name: s.Name }));
const identifiers = Array.from(map.values());
uminder
  • 14,658
  • 3
  • 20
  • 45