聚集表算法: 现有基本表(Base table)以及从基本表对其不同维度(dimensions)值组合(其中*表示所有ALL)进行聚集计算(下图为AVG,取平均)得到的聚集表(Measure)

现有基本表(Base table)以及从基本表对其不同维度(dimensions)值组合(其中*表示所有ALL)进行聚集计算(下图为AVG,取平均)得到的聚集表(Measure),例子如下:

在这里插入图片描述

上图右边的聚集表可展开如下图表示:
在这里插入图片描述

请选择一种擅长的语言设计和实现相关算法,从基本表计算相应的聚集表。

这里是javascript的算法实现:

	// 基本数据     修改基本数据要修改table结构
    let baseArr = [
        ['S1', 'P1', 'Spring', 6],
        ['S1', 'P2', 'Spring', 12],
        ['S2', 'P1', 'Fall', 9],
    ]

    // 数据有效长度,因为sales不计入聚合
    const effeLength = baseArr[0].length - 1;

    // 聚合核心算法
    function aggregate(aggregateArr, baseArr, aggregateVal) {
        let obj = {}; // 使用hash来对相同数据去重(由于对象具有hash的作用,这里直接使用对象就不用map了
        for (let i = 0; i < effeLength; i++) { // 遍历列    01  12 20
            let copyArr = JSON.parse(JSON.stringify(baseArr)) // 深拷贝,防止后续处理污染原始数据
            copyArr.forEach(v => {
                let index = i; // 记录当前聚合列的索引
                for (let j = 0; j < aggregateVal; j++) { // aggregateVal 的值代表聚合的列数
                    v[index] = '*'
                    index++;
                    if (index >= effeLength) {
                        index = 0 // 形成索引环 超过数据长度就从头开始
                    }
                }

                // 将将列合并,方便数据去重,合并相同项,并计算sales和与出现次数(用以计算平均值)
                let key = '';
                for (let j = 0; j < effeLength; j++) {
                    key += v[j] + ','
                }

                if (obj[key]) { // 数据如果已存在,则累加sales值,并记录出现次数
                    obj[key].value += v[effeLength]
                    obj[key].frequency += 1
                } else { // 没有就新建一个
                    obj[key] = {} // obj= {key:{}} <==> obj.key = {}
                    obj[key].value = v[effeLength] // obj.key = {value: sales}
                    obj[key].frequency = 1 // obj.key = {value:sales,frequency:1}
                }
            });
        }
        for (let key in obj) {
            let temp = key.split(','); // 分割出去重后的列
            temp[effeLength] = obj[key].value / obj[key].frequency // 重新计算sales平均值
            aggregateArr.push(temp) // 加入待渲染数组
        }
    }

    // 计算聚集表
    let aggregateArr = [];
    // aggregateVal 为聚合参数, 记录要聚合的列数
    for (let aggregateVal = 0; aggregateVal <= effeLength; aggregateVal++) {
        aggregate(aggregateArr, baseArr, aggregateVal)
    }

结果图:
在这里插入图片描述

完整代码,可以复制到html文件中在浏览器运行。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <div>
            基本表
            <table id="baseTable" border="1px">
                <tr>
                    <td colspan="3">Dimensions</td>
                    <td>Measure</td>
                </tr>
                <tr>
                    <td>Store</td>
                    <td>Product</td>
                    <td>Season</td>
                    <td>Sales</td>
                </tr>
            </table>
        </div>
        <div>
            聚集表
            <table id="aggregateTable" border="1px">
                <tr>
                    <td colspan="3">Dimensions</td>
                    <td>Measure</td>
                </tr>
                <tr>
                    <td>Store</td>
                    <td>Product</td>
                    <td>Season</td>
                    <td>AVG(Sales)</td>
                </tr>
            </table>
        </div>
    </div>
</body>
<script>
    // 基本数据     修改基本数据要修改table结构
    let baseArr = [
        ['S1', 'P1', 'Spring', 6],
        ['S1', 'P2', 'Spring', 12],
        ['S2', 'P1', 'Fall', 9],
    ]

    // 数据有效长度,因为sales不计入聚合
    const effeLength = baseArr[0].length - 1;

    // 将数据渲染为html
    function addDom(table, list) {
        let tr = document.createElement('tr'); // 创建元素tr
        list.forEach(text => {
            let td = document.createElement('td');
            td.innerHTML = text;
            tr.appendChild(td); // 将td挂到tr上
        })
        table.appendChild(tr); // 将新的一行数据挂到table上

    }

    // 聚合核心算法
    function aggregate(aggregateArr, baseArr, aggregateVal) {
        let obj = {}; // 使用hash来对相同数据去重(由于对象具有hash的作用,这里直接使用对象就不用map了
        for (let i = 0; i < effeLength; i++) { // 遍历列    01  12 20
            let copyArr = JSON.parse(JSON.stringify(baseArr)) // 深拷贝,防止后续处理污染原始数据
            copyArr.forEach(v => {
                let index = i; // 记录当前聚合列的索引
                for (let j = 0; j < aggregateVal; j++) { // aggregateVal 的值代表聚合的列数
                    v[index] = '*'
                    index++;
                    if (index >= effeLength) {
                        index = 0 // 形成索引环 超过数据长度就从头开始
                    }
                }

                // 将将列合并,方便数据去重,合并相同项,并计算sales和与出现次数(用以计算平均值)
                let key = '';
                for (let j = 0; j < effeLength; j++) {
                    key += v[j] + ','
                }

                if (obj[key]) { // 数据如果已存在,则累加sales值,并记录出现次数
                    obj[key].value += v[effeLength]
                    obj[key].frequency += 1
                } else { // 没有就新建一个
                    obj[key] = {} // obj= {key:{}} <==> obj.key = {}
                    obj[key].value = v[effeLength] // obj.key = {value: sales}
                    obj[key].frequency = 1 // obj.key = {value:sales,frequency:1}
                }
            });
        }
        for (let key in obj) {
            let temp = key.split(','); // 分割出去重后的列
            temp[effeLength] = obj[key].value / obj[key].frequency // 重新计算sales平均值
            aggregateArr.push(temp) // 加入待渲染数组
        }
    }

    // 渲染基础表
    let baseTable = document.getElementById('baseTable')
    baseArr.forEach(v => {
        addDom(baseTable, v); // 渲染
    })

    // 计算聚集表
    let aggregateArr = [];
    // aggregateVal 为聚合参数, 记录要聚合的列数
    for (let aggregateVal = 0; aggregateVal <= effeLength; aggregateVal++) {
        aggregate(aggregateArr, baseArr, aggregateVal)
    }

    // 渲染聚集表
    let aggregateTable = document.getElementById('aggregateTable')
    aggregateArr.forEach(v => {
        addDom(aggregateTable, v); // 渲染
    })
</script>
<style>
    #app {
        display: flex;
        flex-direction: row;
    }
    
    #app div:nth-child(2) {
        margin-left: 20px;
    }
</style>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值