Задать вопрос
iPirat
@iPirat

JSON Group By и Count (javascript)?

Добрый день!

Подскажите пожалуйста готовое решение или в какую сторону копать, что-бы решить задачу.
Несколько дней уже мучаюсь, нужно сгруппировать и подсчитать value в json (желательно чистый javascript)

Группировка осуществляется через фильтр (максимум 3 группы), по любому из ключей JSON(а) ['date', 'offer', 'epc'] ...
Должен получить что-то вроде такого на выходе 5a37dde5922c2718967968.png

для группировки нашел следующую функцию, она отлично подходит, только не могу понять как сосчитать нужные мне value в группировке (click, etc, unique и тд...)

const group = ['date', 'offer'];

const data = [
	{
		id: '1',
		date: '06.10.2017',
		offer: 'Название1',
		land: 'land1',
		click: 1000000,
		unique: 13.33,
		epc: 66.66,
		cr: 66.66,
		sr: 66.66,
		dialing:66.66,
		apruvDozv:66.66,
		apruv:11.00,
		total:100000,
		accepted:100000,
		wait:100000,
		cancel:10000,
		trash:100000,
		accruedmoney: 100000,
		cancelmoney: 132222
	},
	{
		id: '2',
		date: '06.10.2017',
		offer: 'Название1',
		land: 'land2',
		click: 1000000,
		unique: 13.33,
		epc: 66.66,
		cr: 66.66,
		sr: 66.66,
		dialing:66.66,
		apruvDozv:66.66,
		apruv:11.00,
		total:100000,
		accepted:100000,
		wait:100000,
		cancel:10000,
		trash:100000,
		accruedmoney: 100000,
		cancelmoney: 132222
	},
	{
		id: '3',
		date: '06.10.2017',
		offer: 'Название2',
		land: 'land3',
		click: 1000000,
		unique: 13.33,
		epc: 66.66,
		cr: 66.66,
		sr: 66.66,
		dialing:66.66,
		apruvDozv:66.66,
		apruv:11.00,
		total:100000,
		accepted:100000,
		wait:100000,
		cancel:10000,
		trash:100000,
		accruedmoney: 100000,
		cancelmoney: 132222
	},				{
		id: '4',
		date: '06.10.2017',
		offer: 'Название2',
		land: 'land4',
		click: 1000000,
		unique: 13.33,
		epc: 66.66,
		cr: 66.66,
		sr: 66.66,
		dialing:66.66,
		apruvDozv:66.66,
		apruv:11.00,
		total:100000,
		accepted:100000,
		wait:100000,
		cancel:10000,
		trash:100000,
		accruedmoney: 100000,
		cancelmoney: 132222
	},
	{
		id: '5',
		date: '10.10.2017',
		offer: 'Название3',
		land: 'land5',
		click: 1000000,
		unique: 13.33,
		epc: 66.66,
		cr: 66.66,
		sr: 66.66,
		dialing:66.66,
		apruvDozv:66.66,
		apruv:11.00,
		total:100000,
		accepted:100000,
		wait:100000,
		cancel:10000,
		trash:100000,
		accruedmoney: 100000,
		cancelmoney: 132222
	},
	{
		id: '6',
		date: '11.10.2017',
		offer: 'Название4',
		land: 'land6',
		click: 1000000,
		unique: 13.33,
		epc: 66.66,
		cr: 66.66,
		sr: 66.66,
		dialing:66.66,
		apruvDozv:66.66,
		apruv:11.00,
		total:100000,
		accepted:100000,
		wait:100000,
		cancel:10000,
		trash:100000,
		accruedmoney: 100000,
		cancelmoney: 132222
	},
	{
		id: '7',
		date: '12.10.2017',
		offer: 'Название1',
		land: 'land7',
		click: 1000000,
		unique: 13.33,
		epc: 66.66,
		cr: 66.66,
		sr: 66.66,
		dialing:66.66,
		apruvDozv:66.66,
		apruv:11.00,
		total:100000,
		accepted:100000,
		wait:100000,
		cancel:10000,
		trash:100000,
		accruedmoney: 100000,
		cancelmoney: 132222
	}
];

function getItemByKey(arr, key, value){
	// here we look for existing group item in the result array
	return arr.reduce(function (prev, cur) {
		if (prev == null && cur[key] == value) {
			return cur;
		}
		return prev;
	}, null);
}

function checkPropForGroup(prop, key){
	// here we check which columns should stay in the group,
	// and which should go down to group items.
	return prop == key || prop == key.replace("_id", "_name");
}

function cloneSuperItem(src, key){
	// create super item by copying only group related fields 
	var item = {};
	for (var prop in src){
		if (checkPropForGroup(prop, key)){
			item[prop] = src[prop];
		}
	}
	item[key+'_group'] = [];
	return item;
}

function cloneSubItem(src, key){
	// create sub-item by copying all but group related fields 
	var item = {};
	for (var prop in src){
		if (!checkPropForGroup(prop, key)){
			item[prop] = src[prop];
		}
	}
	return item;
}

function groupArray(arr, args, lvl){
	var key = args[lvl];
	var result = [];
	arr.forEach(function (item, ind, a){
		// find or create super item for group and then create sub item and push it there 
		var keyItem = getItemByKey(result, key, item[key]);
		if (!keyItem){
			keyItem = cloneSuperItem(item, key);
			result.push(keyItem);
		}
		var subItem = cloneSubItem(item, key);
		keyItem[key+'_group'].push(subItem);
	});
	if (args[lvl+1]){
		// recursively make grouping on lower level 
		for (var i = 0; i < result.length; i++){
			result[i][key+'_group'] = groupArray(result[i][key+'_group'], args, lvl + 1);
		}
	}
	return result;
}

function groupArrayMain(arr, keysArray){
	// keys should be simply listed as parameters in order from top group to lower
	return groupArray(arr, arguments, 1)
}


groups = groups.filter(function(item) { 
    return item !== undefined
})

console.log( groupArrayMain(...[data, ...[...groups]]) )
  • Вопрос задан
  • 562 просмотра
Подписаться 1 Простой 2 комментария
Решения вопроса 1
NightmareZz
@NightmareZz
Нищий разработчик из Симферополя
Используй библиотеки underscore или lodash, - в них есть готовые функции groupBy.
Если не нужна поддержка старых браузеров, можно использовать функцию reduce из JavaScript 1.8
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы