前端对后台返回的集合分组求和

前端对集合分组求和

项目需求:现在有一个需求,根据集合中某一对象的键值,对集合中相同键值的对象重新求和。如

 [{name: 'Jack',country:1,score:68},
  {name: 'Peter',country:1,score:75},
  {name: 'Jason',country:2,score:55},
  {name: 'David',country:2,score:89},
  {name: 'Sean',country:3,score:85},
  {name: 'Andy',country:3,score:99}]

这样一组集合,前端直接渲染成表格是这样的。

namecountryscore
Jack168
Peter175
Jason255
David289
Sean385
Andy399

至于如何渲染成这样的,可以使用for循环,使用键值对,js动态插入到dom节点中。

//渲染表格
var str = '';
for(var i=0;i<obj.length;i++){
	str += '<tr>'
	str += '<td>'+obj[i].name+'<td>'
	str += '<td>'+obj[i].grage+'<td>'
	str += '<td>'+obj[i].score+'<td>'
	str += '</tr>'
}

但是现在我想要的是各个国家的总分数,应该是这样的表格

namegragescore
Jack168
Peter175
国家得分小计1143
Jason255
David289
国家得分小计2144
Sean385
Andy399
国家得分小计3184

这个应该是数据库中的一个分组求和的算法,那么如果我们的后台不够强大,只能够给我提供最简单的数据查询支持,而不提供分组求和的功能,那么纯粹前端如何实现呢?


function groupBy(obj) {
    var newObj1 = new Array();
	var newObj2 = JSON.parse(JSON.stringify(obj));
	var index1 = 0;
	var sum = -1;
	for(var i = 0; i < newObj2.length; i++) {
		newObj2[i].name = '国家积分小计'
		if(i == 0) {
			newObj1[i] = newObj2[i];
		} else {
			var res = newObj1.filter((item, index, arr) => {
				if(newObj2[i].country == item.country) {
					index1 = index;
				}
				return newObj2[i].country == item.country;
			})
			if(res.length == 0) {
				newObj1.push(newObj2[i])
				sum++;
				obj.splice(i + sum, 0, newObj1[index1])
			} else {
				newObj1[index1].score += newObj2[i].score;
			}
		}
	}
	obj[obj.length] = newObj1[index1];
	return obj;
}

这是重算完返回的数据:

      [{"name":"Jack","country":1,"score":68},      
       {"name":"Peter","country":1,"score":75},
       {"name":"国家积分小计","country":1,"score":143},  
       {"name":"Jason","country":2,"score":55},   
       {"name":"David","country":2,"score":89},
       {"name":"国家积分小计","country":2,"score":144}, 
       {"name":"Sean","country":3,"score":85},
       {"name":"Andy","country":3,"score":99},
       {"name":"国家积分小计","country":3,"score":184

可以看到集合已经变成了我们想要的模样,现在只需要重新写进去便可以了。就能展示出来我们想要的结果。还可以在渲染界面的时候,根据当前name,是否为‘国家积分小计’,对单行数据重新调整样式,便可以了。
那么回头可以来看一下,究竟是如何实现的呢。首先逐条解析代码:

var newObj1 = new Array();
var newObj2 = JSON.parse(JSON.stringify(obj));
var index1 = 0;
var sum = -1;

这是生命的对象和变量,可以发现newObj2 这个对象,是由传入的obj对象复制而来,这是深拷贝的结果,关于深拷贝和浅拷贝的问题,可以自己查询一下,现在这是一个新的对象,并且和obj是一样的。

 for(var i = 0; i < newObj2.length; i++) {
	newObj2[i].name = '国家积分小计'
	if(i == 0) {
		newObj1[i] = newObj2[i];
	} else {
		var res = newObj1.filter((item, index, arr) => {
			if(newObj2[i].country == item.country) {
				index1 = index;
			}
			return newObj2[i].country == item.country;
		})
		if(res.length == 0) {
			newObj1.push(newObj2[i])
			sum++;
			obj.splice(i + sum, 0, newObj1[index1])
		} else {
			newObj1[index1].score += newObj2[i].score;
		}
	}
}

在这段循环中,可以看出来是newObj2集合的循环,首先将集合中的每个对象的name设置为国家积分小计,首先将newObj2的第一个对象赋给newObj1的第一个对象,这是方便使用js中的filter方法,关于这种方法,不知道的可以查询。在第一行以后,开始判断newObj2当前对象是否在newObj1之中,如果在,则使用index1 去记录下来newObj1的下标,即要知道,对应于newObj1的哪一个对象。如果res.length的结果为0,则说明newObj1不存在与当前newObj2国家相同的对象,便将当前newObj2的对象添加到newObj1中。并且在原集合obj中,添加这一对象。如果res.length不为0,则说明当前国家是一样的,便在newObj2的得分中加上当前newObj1的得分。接下来依次循环。最后将newObj2的最后一个对象添加到newObj1中。
总结一下,即首先复制一个当前集合用于编辑,再创建一个空集合用于储存分组求和的集合。最后将分组求和的集合,按国家名称依次写入到原集合中。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值