Search code examples
javascriptarraystypescriptangular5lodash

Find unique element in an array and the find the sum of field(say Marks) for the duplicate elements


This question may be similar to In Angular2 *ngFor iteration, how do I output only unique values from the array? but my question is have some more features.

I have a list of the following form

    let studentsList = [{
        name:'A',
        rollNo:1,
        mark:10
    },
    {
        name:'B',
        rollNo:2,
        mark:30
    },
    {
        name:'C',
        rollNo:3,
        mark:40
    },
    {
        name:'A',
        rollNo:1,
        mark:50
    }
  ]

The objective is to display unique name and marks from the studentList and find the unique name from it like this.

A   10
B   30
C   40

Also if the name repeats then add the marks and display.

A   60
B   30
C   40

I could filter the unique names like this

import { Pipe, PipeTransform } from '@angular/core';
import * as _ from 'lodash'; 

@Pipe({
  name: 'unique',
  pure: false
})

    export class UniquePipe implements PipeTransform {
        transform(value: any): any{
            if(value!== undefined && value!== null){
                return _.uniqBy(value, 'name');
            }
            return value;
        }
    }

then in html

<ul>
  <li *ngFor="let student of studentList| unique">
    {{student .name}}
  </li>
</ul>

Edit

The studentsList is dynamic we can add as many details needed.


Solution

  • If you need a result array of name and marks (sum of duplicates) then you can do that with a very cleaner way in lodash (since you tagged lodash). _.groupBy will always group it by its unique parameter and group all duplivates with that parameter inside a array for each group.

    1. First, group it by name using _.groupBy
    2. Then map (.map) each group and calculate sum of marks by .sumBy

    Here is an working example:

    let input = [{"name":"A","rollNo":1,"mark":10},{"name":"B","rollNo":2,"mark":30},{"name":"C","rollNo":3,"mark":40},{"name":"A","rollNo":1,"mark":50}],
        res = _(input)
                .groupBy('name')
                .map((g, name) => ({name, mark: _.sumBy(g, 'mark')}))
                .value();
                
    console.log(res);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>