如何通过提供动态组和求和值在 JavaScript 中创建层级数据?
How to create hierarchy data in JavaScript by providing dynamic groups and summing the value?
我想创建一个基于我的组的动态层次结构并将总和汇总到顶层,如果我提供大量数据,浏览器就会挂起。
我有以下数据:
var data = [
{
"country":"Spain",
"orderNumber":10394,
"year":2018,
"countrycode":"es",
"quantityOrdered":30,
"priceEach":60.28,
"productName":"1950's Chicago Surface Lines Streetcar",
"productLine":"Trains",
"sortkey":3,
"productCode":"S32_3207",
"month":"March",
"extendedPrice":1808.4,
"orderDate":"2018-03-15 00:00:00"
},
{
"country":"France",
"orderNumber":10395,
"year":2018,
"countrycode":"fr",
"quantityOrdered":32,
"priceEach":105.33,
"productName":"1972 Alfa Romeo GTA",
"productLine":"Classic Cars",
"sortkey":3,
"productCode":"S10_4757",
"month":"March",
"extendedPrice":3370.56,
"orderDate":"2018-03-17 00:00:00"
},
{
"country":"France",
"orderNumber":10395,
"year":2018,
"countrycode":"fr",
"quantityOrdered":33,
"priceEach":69.12,
"productName":"2001 Ferrari Enzo",
"productLine":"Classic Cars",
"sortkey":3,
"productCode":"S12_1108",
"month":"March",
"extendedPrice":2280.96,
"orderDate":"2018-03-17 00:00:00"
},
{
"country":"France",
"orderNumber":10395,
"year":2018,
"countrycode":"fr",
"quantityOrdered":46,
"priceEach":123.76,
"productName":"Diamond T620 Semi-Skirted Tanker",
"productLine":"Trucks and Buses",
"sortkey":3,
"productCode":"S50_1392",
"month":"March",
"extendedPrice":5692.96,
"orderDate":"2018-03-17 00:00:00"
},
{
"country":"France",
"orderNumber":10395,
"year":2018,
"countrycode":"fr",
"quantityOrdered":45,
"priceEach":199.49,
"productName":"1962 City of Detroit Streetcar",
"productLine":"Trains",
"sortkey":3,
"productCode":"S50_1514",
"month":"March",
"extendedPrice":8977.05,
"orderDate":"2018-03-17 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":33,
"priceEach":185.13,
"productName":"1969 Ford Falcon",
"productLine":"Classic Cars",
"sortkey":3,
"productCode":"S12_3891",
"month":"March",
"extendedPrice":6109.29,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":33,
"priceEach":159.81,
"productName":"1903 Ford Model A",
"productLine":"Vintage Cars",
"sortkey":3,
"productCode":"S18_3140",
"month":"March",
"extendedPrice":5273.73,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":24,
"priceEach":89.75,
"productName":"Collectable Wooden Train",
"productLine":"Trains",
"sortkey":3,
"productCode":"S18_3259",
"month":"March",
"extendedPrice":2154,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":45,
"priceEach":105.32,
"productName":"1904 Buick Runabout",
"productLine":"Vintage Cars",
"sortkey":3,
"productCode":"S18_4522",
"month":"March",
"extendedPrice":4739.4,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":49,
"priceEach":116.75,
"productName":"18th century schooner",
"productLine":"Ships",
"sortkey":3,
"productCode":"S24_2011",
"month":"March",
"extendedPrice":5720.75,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":27,
"priceEach":83.2,
"productName":"1912 Ford Model T Delivery Wagon",
"productLine":"Vintage Cars",
"sortkey":3,
"productCode":"S24_3151",
"month":"March",
"extendedPrice":2246.4,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":37,
"priceEach":90.57,
"productName":"1940 Ford Delivery Sedan",
"productLine":"Vintage Cars",
"sortkey":3,
"productCode":"S24_3816",
"month":"March",
"extendedPrice":3351.09,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":39,
"priceEach":66.67,
"productName":"The Schooner Bluenose",
"productLine":"Ships",
"sortkey":3,
"productCode":"S700_1138",
"month":"March",
"extendedPrice":2600.13,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"France",
"orderNumber":10397,
"year":2018,
"countrycode":"fr",
"quantityOrdered":32,
"priceEach":80.55,
"productName":"The Mayflower",
"productLine":"Ships",
"sortkey":3,
"productCode":"S700_1938",
"month":"March",
"extendedPrice":2577.6,
"orderDate":"2018-03-28 00:00:00"
}
]
我创建了以下函数,但它无法正常工作
var groups = ['country', 'productLine', 'month']; // this can be dynamic
var sum = ['priceEach']; // this can be dynamic
function createGroup (groups, data, sum, childNode) {
let [primaryGroup, ...rest] = groups;
let groupedData = data.reduce((acc, current) => {
let chunk = {
'Name': current[primaryGroup],
[primaryGroup]: current[primaryGroup],
[sum]: data.filter(item => item[primaryGroup] === current[primaryGroup])
.map(el => el[sum])
.reduce((total, current) => total + current),
...(rest.length > 0 ? {[groups[childNode]]: createGroup(rest, data, sum,childNode+1 )} : {})
}
acc.push(chunk)
return acc
}, [])
.reduce((acc, current) => {
const x = acc.find(item => item[primaryGroup] === current[primaryGroup])
return !x ? acc.concat([current]) : acc
}, [])
return groupedData;
}
const tree = createGroup(groups,data,sum, 1);
示例结果下方需要(我没有包括其他国家,但我需要全部)
[
{
"country":[
{
"Name":"Spain",
"priceEach":60.28,
"productline":[
{
"Name":"Trains",
"priceEach":60.28,
"month":[
{
"Name":"March",
"priceEach":60.28
}
]
}
]
}
]
},
{
"country":[
{
"Name":"France",
"priceEach":578.25,
"productline":[
{
"Name":"Classic Cars",
"priceEach":174.45,
"month":[
{
"Name":"March",
"priceEach":174.45
}
]
},
{
"Name":"Trucks and Buses",
"priceEach":123.76,
"month":[
{
"Name":"March",
"priceEach":123.76
}
]
},
{
"Name":"Trains",
"priceEach":199.49,
"month":[
{
"Name":"April",
"priceEach":199.49
}
]
},
{
"Name":"Ships",
"priceEach":80.55,
"month":[
{
"Name":"June",
"priceEach":80.55
}
]
}
]
}
]
}
]
嗯,可能是 hangs
因为 O(n log n)
(你一遍又一遍地重复相同的 data
)。
注意:priceEach
在这个方案中是静态的,但是你可以重新设计递归函数
function createGroup(groups, i, data, parent){
//Take current group
var group = groups[i];
var nGroup = groups[i+1];
// No more group, stop recursivity
if (!group) return parent;
// Now, let's reduce by current group
//FIX: We need to add an empty item to force the reduce method
if(data.length == 1) {
data.push({priceEach:0});
}
var root = data.reduce((prev, next) => {
//First time, add prev value
if(parent.length == 0) {
var item = {};
item[group] = {
"Name": prev[group],
"priceEach": prev.priceEach
}
//Next group?
if(nGroup){
item[group][nGroup] = createGroup(groups, i+1, [prev], []);
}
parent.push(item);
}
//Check if we need to reduce
for(var item of parent){
if(item[group].Name == next[group]) {
item[group].priceEach += next.priceEach;
//Next group?
if(nGroup){
item[group][nGroup] = createGroup(groups, i+1, [prev, next], item[group][nGroup]);
}
return parent;
}
}
//We did not reduce, so add next as item
if(next[group]) {
var item = {};
item[group] = {
"Name": next[group],
"priceEach": next.priceEach
}
//Next group?
if(nGroup){
item[group][nGroup] = createGroup(groups, i+1, [next], []);
}
parent.push(item);
}
return parent;
});
return root;
}
createGroup(["country", "productLine", "month"], 0, data, []);
如果 country, productLine, month
是静态的,您可以 运行 classic way
我想创建一个基于我的组的动态层次结构并将总和汇总到顶层,如果我提供大量数据,浏览器就会挂起。
我有以下数据:
var data = [
{
"country":"Spain",
"orderNumber":10394,
"year":2018,
"countrycode":"es",
"quantityOrdered":30,
"priceEach":60.28,
"productName":"1950's Chicago Surface Lines Streetcar",
"productLine":"Trains",
"sortkey":3,
"productCode":"S32_3207",
"month":"March",
"extendedPrice":1808.4,
"orderDate":"2018-03-15 00:00:00"
},
{
"country":"France",
"orderNumber":10395,
"year":2018,
"countrycode":"fr",
"quantityOrdered":32,
"priceEach":105.33,
"productName":"1972 Alfa Romeo GTA",
"productLine":"Classic Cars",
"sortkey":3,
"productCode":"S10_4757",
"month":"March",
"extendedPrice":3370.56,
"orderDate":"2018-03-17 00:00:00"
},
{
"country":"France",
"orderNumber":10395,
"year":2018,
"countrycode":"fr",
"quantityOrdered":33,
"priceEach":69.12,
"productName":"2001 Ferrari Enzo",
"productLine":"Classic Cars",
"sortkey":3,
"productCode":"S12_1108",
"month":"March",
"extendedPrice":2280.96,
"orderDate":"2018-03-17 00:00:00"
},
{
"country":"France",
"orderNumber":10395,
"year":2018,
"countrycode":"fr",
"quantityOrdered":46,
"priceEach":123.76,
"productName":"Diamond T620 Semi-Skirted Tanker",
"productLine":"Trucks and Buses",
"sortkey":3,
"productCode":"S50_1392",
"month":"March",
"extendedPrice":5692.96,
"orderDate":"2018-03-17 00:00:00"
},
{
"country":"France",
"orderNumber":10395,
"year":2018,
"countrycode":"fr",
"quantityOrdered":45,
"priceEach":199.49,
"productName":"1962 City of Detroit Streetcar",
"productLine":"Trains",
"sortkey":3,
"productCode":"S50_1514",
"month":"March",
"extendedPrice":8977.05,
"orderDate":"2018-03-17 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":33,
"priceEach":185.13,
"productName":"1969 Ford Falcon",
"productLine":"Classic Cars",
"sortkey":3,
"productCode":"S12_3891",
"month":"March",
"extendedPrice":6109.29,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":33,
"priceEach":159.81,
"productName":"1903 Ford Model A",
"productLine":"Vintage Cars",
"sortkey":3,
"productCode":"S18_3140",
"month":"March",
"extendedPrice":5273.73,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":24,
"priceEach":89.75,
"productName":"Collectable Wooden Train",
"productLine":"Trains",
"sortkey":3,
"productCode":"S18_3259",
"month":"March",
"extendedPrice":2154,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":45,
"priceEach":105.32,
"productName":"1904 Buick Runabout",
"productLine":"Vintage Cars",
"sortkey":3,
"productCode":"S18_4522",
"month":"March",
"extendedPrice":4739.4,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":49,
"priceEach":116.75,
"productName":"18th century schooner",
"productLine":"Ships",
"sortkey":3,
"productCode":"S24_2011",
"month":"March",
"extendedPrice":5720.75,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":27,
"priceEach":83.2,
"productName":"1912 Ford Model T Delivery Wagon",
"productLine":"Vintage Cars",
"sortkey":3,
"productCode":"S24_3151",
"month":"March",
"extendedPrice":2246.4,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":37,
"priceEach":90.57,
"productName":"1940 Ford Delivery Sedan",
"productLine":"Vintage Cars",
"sortkey":3,
"productCode":"S24_3816",
"month":"March",
"extendedPrice":3351.09,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"USA",
"orderNumber":10396,
"year":2018,
"countrycode":"us",
"quantityOrdered":39,
"priceEach":66.67,
"productName":"The Schooner Bluenose",
"productLine":"Ships",
"sortkey":3,
"productCode":"S700_1138",
"month":"March",
"extendedPrice":2600.13,
"orderDate":"2018-03-23 00:00:00"
},
{
"country":"France",
"orderNumber":10397,
"year":2018,
"countrycode":"fr",
"quantityOrdered":32,
"priceEach":80.55,
"productName":"The Mayflower",
"productLine":"Ships",
"sortkey":3,
"productCode":"S700_1938",
"month":"March",
"extendedPrice":2577.6,
"orderDate":"2018-03-28 00:00:00"
}
]
我创建了以下函数,但它无法正常工作
var groups = ['country', 'productLine', 'month']; // this can be dynamic
var sum = ['priceEach']; // this can be dynamic
function createGroup (groups, data, sum, childNode) {
let [primaryGroup, ...rest] = groups;
let groupedData = data.reduce((acc, current) => {
let chunk = {
'Name': current[primaryGroup],
[primaryGroup]: current[primaryGroup],
[sum]: data.filter(item => item[primaryGroup] === current[primaryGroup])
.map(el => el[sum])
.reduce((total, current) => total + current),
...(rest.length > 0 ? {[groups[childNode]]: createGroup(rest, data, sum,childNode+1 )} : {})
}
acc.push(chunk)
return acc
}, [])
.reduce((acc, current) => {
const x = acc.find(item => item[primaryGroup] === current[primaryGroup])
return !x ? acc.concat([current]) : acc
}, [])
return groupedData;
}
const tree = createGroup(groups,data,sum, 1);
示例结果下方需要(我没有包括其他国家,但我需要全部)
[
{
"country":[
{
"Name":"Spain",
"priceEach":60.28,
"productline":[
{
"Name":"Trains",
"priceEach":60.28,
"month":[
{
"Name":"March",
"priceEach":60.28
}
]
}
]
}
]
},
{
"country":[
{
"Name":"France",
"priceEach":578.25,
"productline":[
{
"Name":"Classic Cars",
"priceEach":174.45,
"month":[
{
"Name":"March",
"priceEach":174.45
}
]
},
{
"Name":"Trucks and Buses",
"priceEach":123.76,
"month":[
{
"Name":"March",
"priceEach":123.76
}
]
},
{
"Name":"Trains",
"priceEach":199.49,
"month":[
{
"Name":"April",
"priceEach":199.49
}
]
},
{
"Name":"Ships",
"priceEach":80.55,
"month":[
{
"Name":"June",
"priceEach":80.55
}
]
}
]
}
]
}
]
嗯,可能是 hangs
因为 O(n log n)
(你一遍又一遍地重复相同的 data
)。
注意:priceEach
在这个方案中是静态的,但是你可以重新设计递归函数
function createGroup(groups, i, data, parent){
//Take current group
var group = groups[i];
var nGroup = groups[i+1];
// No more group, stop recursivity
if (!group) return parent;
// Now, let's reduce by current group
//FIX: We need to add an empty item to force the reduce method
if(data.length == 1) {
data.push({priceEach:0});
}
var root = data.reduce((prev, next) => {
//First time, add prev value
if(parent.length == 0) {
var item = {};
item[group] = {
"Name": prev[group],
"priceEach": prev.priceEach
}
//Next group?
if(nGroup){
item[group][nGroup] = createGroup(groups, i+1, [prev], []);
}
parent.push(item);
}
//Check if we need to reduce
for(var item of parent){
if(item[group].Name == next[group]) {
item[group].priceEach += next.priceEach;
//Next group?
if(nGroup){
item[group][nGroup] = createGroup(groups, i+1, [prev, next], item[group][nGroup]);
}
return parent;
}
}
//We did not reduce, so add next as item
if(next[group]) {
var item = {};
item[group] = {
"Name": next[group],
"priceEach": next.priceEach
}
//Next group?
if(nGroup){
item[group][nGroup] = createGroup(groups, i+1, [next], []);
}
parent.push(item);
}
return parent;
});
return root;
}
createGroup(["country", "productLine", "month"], 0, data, []);
如果 country, productLine, month
是静态的,您可以 运行 classic way