在数组中查找唯一元素,然后查找重复元素的字段总和(例如Marks)

时间:2019-03-14 05:37:24

标签: javascript arrays typescript angular5 lodash

这个问题可能类似于In Angular2 *ngFor iteration, how do I output only unique values from the array?,但我的问题还有更多功能。

我有以下表格的列表

    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
    }
  ]

目标是显示studentList中的唯一名称和标记,并从中查找唯一名称。

A   10
B   30
C   40

如果名称重复,则添加标记并显示。

A   60
B   30
C   40

我可以像这样过滤唯一的名称

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;
        }
    }

然后用html

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

编辑

studentsList是动态的,我们可以添加所需的详细信息。

4 个答案:

答案 0 :(得分:2)

如果您需要一个由名称和标记组成的结果数组(重复项的总和),则可以在lodash中使用一种更加简洁的方法来完成此操作(因为您已标记lodash)。 _.groupBy将始终按其唯一参数对其进行分组,并在每个组的数组内将所有与该参数重复的结果分组。

  1. 首先,使用_.groupBy通过name将其分组
  2. 然后对每个组进行映射(.map )并通过 .sumBy
  3. 计算标记总数

这是一个有效的示例:

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>

答案 1 :(得分:0)

您可以在管道中使用此功能:

value.reduce((acc, ele) => {
  const existingStudent = acc.find(x => x.name === ele.name);
  if(!existingStudent) return acc.concat(ele);
  return (existingStudent.mark += ele.mark, acc);
},[])

测试:

var 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}];

const resp = studentsList.reduce((acc, ele) => {
  const existingStudent = acc.find(x => x.name === ele.name);
  if(!existingStudent) return acc.concat(ele);
  return (existingStudent.mark += ele.mark, acc);
},[])

console.log(resp);

答案 2 :(得分:0)

示例如何累积您的值。

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 }
];

const byName = {};
for (var student of studentsList) {
  if (student.name in byName) {
    byName[student.name].mark += student.mark;
  } else {
    byName[student.name] = { ...student };
  }
}
console.log(Object.values(byName));

答案 3 :(得分:0)

您可以将学生数组分组到卷号上,并在对象累加器中添加相同卷号的标记。使用array#values()获取与卷号相对应的所有值。

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 } ],
    uniqueStudents = Object.values(studentsList.reduce((r,{name, rollNo, mark}) => {
      r[rollNo] = r[rollNo] || {name, rollNo, total : 0};
      r[rollNo].total += mark;
      return r;
    },{}));
console.log(uniqueStudents);