原谅n00b-ish问题,但我是数据结构的新手。我最近被要求将一个给定的数组聚合在另一个数组上,并产生一个基于树的结果。
有人可以给我一些关于如何获得这个输出的指示吗?
INPUT
TOTAL 29900
Female <Female Total>
Single <Single Female Total>
India <Single Female Total India>
England <Single Female Total England>
Married <Married Female Total>
India <Married Female Total India>
England <Married Female Total England>
Male <Male Total>
Single <Single Male Total>
India <Single Male Total India>
England <Single Male Total England>
Married <Married Male Total>
India <Married Male Total India>
England <Married Male Total England>
输出:为每个叶节点使用2 *个空格。
{{1}}
答案 0 :(得分:6)
结果可以用嵌套对象表示,每个内部对象都是一个子树,其总数为:
{
total: 29900,
Female: {
total: 10300,
Single: {
total: 4000,
India: {
total: 2400
},
...
},
...
},
...
}
只需遍历所有条目,然后将值添加到相应的子树节点。
对于输出,您可以使用JSON.stringify
并从中删除不必要的文本。
警告:以下剧透
const T = [
['COUNTRY', 'GENDER', 'MARITAL STATUS', 'SALES'],
['India', 'Female', 'Single', 2400],
['India', 'Male', 'Single', 5200],
['India', 'Female', 'Married', 4300],
['India', 'Male', 'Single', 3200],
['England', 'Female', 'Single', 1600],
['England', 'Female', 'Married', 2000],
['England', 'Male', 'Single', 4800],
['England', 'Male', 'Married', 6400],
]
const A = ['GENDER', 'MARITAL STATUS', 'COUNTRY']
function aggregate(T, A) {
const [fields, ...data] = T
const columns = A.map(name => fields.findIndex(it => name === it))
const count = fields.length - 1
const result = { total: 0 }
data.forEach(values => {
result.total += values[count]
//Go through the tree path, reduce is used here
//to avoid creating extra tracking variable for current position
columns.reduce((ref, index) => {
const key = values[index]
const next = ref[key] || (ref[key] = { total: 0 })
next.total += values[count]
return next
}, result)
})
return result
}
function pack(data) {
return Object.keys(data).reduce((result, key) => {
if (key !== 'total') {
const name = key + " " + data[key].total
result[name] = pack(data[key])
}
return result
}, {})
}
function format(result) {
return JSON.stringify(pack(result), null, 2)
.replace(/[^A-z0-9\n\s]/g, '')
.replace(/\n?\s*\n/g, '\n')
}
function output(it) {
const result = "TOTAL " + it.total + format(it)
console.log(result)
}
output(aggregate(T, A))
&#13;
答案 1 :(得分:2)
使用树结构的常用方法是将它们表示为嵌套对象,如DarkKnight's answer所示,然后从此数据结构中创建字符串表示。
在OP提供的情况下,另一种方法是首先对数据进行排序,然后直接从排序数据创建树的字符串表示,而不需要任何嵌套对象的中间数据结构。
给定要聚合的列数组,
@Override
public int getCount() {
return items.size();
}
我们可以按以下列对数据进行排序:
['GENDER', 'MARITAL STATUS', 'COUNTRY']
从最后一行向后循环,在聚合时,我们可以自下而上构建树的字符串表示形式。最后一行与之前的第3行(COUNTRY)不同,它提供以下输出:
GENDER STATUS COUNTRY SALES
Female Single India 2400
Female Single England 1600
Female Married India 4300
Female Married England 2000
Male Single India 5200
Male Single England 4800
Male Married India 3200
Male Married England 6400
之前的行在3级(COUNTRY)和2级(MARITAL STATUS)上有所不同,前面是当前输出:
England 6400
在此之前的行之后:
Married 9600
India 3200
England 6400
然后,第5行与前3行不同:
England 4800
Married 9600
India 3200
England 6400
依此类推,直到代表整个树:
Male 19600
Single 10000
India 5200
England 4800
Married 9600
India 3200
England 6400
以下是工作代码(符合ES3),演示了该方法。
Total 29900
Female 10300
Single 4000
India 2400
England 1600
Married 6300
India 4300
England 2000
Male 19600
Single 10000
India 5200
England 4800
Married 9600
India 3200
England 6400
答案 2 :(得分:2)
Tree是实现此问题的不错选择。您也可以在一次性通行证中进行聚合。基本理念是
按给定列对数据进行排序。
循环数组,检查给定列的值
2.1如果列的值与上一行
相同,则汇总组计数2.2输出组名称和计数,如果列的值与上一行不同
这是一个我引导CS学生完成作业的例子,与你的作业非常相似。
Here处的sumaryStage3方法实现了步骤2的逻辑。
请忽略代码风格和质量。这不是我的代码。