首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

JavaScript 處理 JSON 數據轉換為 HTML 表格:從長數據到寬表格的重構實戰

     編輯:程式設計綜合問答

數據結構分析

原始數據為「長格式」(Long Format):每行一條記錄,包含維度(XMID、ysdate)與度量值(SZH)。目標轉為「寬格式」(Wide Format):ysdate 為行,XMID 為列,SZH 為單元格值。

// 原始數據結構
const json = {
  "Table1": [
    {"XMID": "B0", "ysdate": "2015-01-01T00:00:00", "SZH": 7373.0},
    {"XMID": "B0", "ysdate": "2015-01-02T00:00:00", "SZH": 7845.0},
    {"XMID": "C0", "ysdate": "2015-01-01T00:00:00", "SZH": 327.0},
    // ... 更多記錄
  ]
};

核心演算法:樞紐轉換

function pivotToTable(data, rowKey, colKey, valueKey) {
    // 1. 分組聚合:以 rowKey 為鍵,收集所有 colKey→valueKey 映射
    const rows = {};
    const columns = new Set();

    data.forEach(record => {
        const rowVal = record[rowKey];
        const colVal = record[colKey];
        const val = record[valueKey];

        if (!rows[rowVal]) rows[rowVal] = {};
        rows[rowVal][colVal] = val;  // 同一 row+col 取最後值,或根據業務合併
        columns.add(colVal);
    });

    // 2. 排序列(保證表頭順序穩定)
    const sortedCols = Array.from(columns).sort();

    // 3. 生成 HTML 表格
    let html = '';
    
    // 表頭
    html += '';
    sortedCols.forEach(col => html += '');
    html += '';

    // 數據行(按行鍵排序)
    html += '';
    Object.keys(rows).sort().forEach(rowVal => {
        html += '';
        sortedCols.forEach(col => {
            const cellVal = rows[rowVal][col];
            html += '';
        });
        html += '';
    });
    html += '
' + rowKey + '' + col + '
' + formatDate(rowVal) + '' + (cellVal !== undefined ? cellVal : '') + '
'; return html; } // 日期格式化:移除時間部分 function formatDate(isoString) { return isoString.split('T')[0]; // "2015-01-01T00:00:00" → "2015-01-01" } // 使用 const tableHtml = pivotToTable(json.Table1, 'ysdate', 'XMID', 'SZH'); document.getElementById('container').innerHTML = tableHtml;

進階版:支援多值聚合與配置化

class DataPivot {
    constructor(options = {}) {
        this.rowKey = options.rowKey || 'ysdate';
        this.colKey = options.colKey || 'XMID';
        this.valueKey = options.valueKey || 'SZH';
        this.aggregator = options.aggregator || ((a, b) => b); // 預設取最後值
        this.dateFormat = options.dateFormat || (s => s.split('T')[0]);
        this.colSort = options.colSort || ((a, b) => a.localeCompare(b));
        this.rowSort = options.rowSort || ((a, b) => a.localeCompare(b));
        this.missingCell = options.missingCell || '';
    }

    transform(data) {
        const rows = {};
        const cols = new Set();

        data.forEach(r => {
            const rv = r[this.rowKey];
            const cv = r[this.colKey];
            const vv = r[this.valueKey];
            if (!rows[rv]) rows[rv] = {};
            // 聚合邏輯:首次賦值或自定義聚合
            rows[rv][cv] = rows[rv][cv] === undefined ? vv : this.aggregator(rows[rv][cv], vv);
            cols.add(cv);
        });

        const sortedCols = Array.from(cols).sort(this.colSort);
        const sortedRows = Object.keys(rows).sort(this.rowSort);

        // 構建表頭
        let html = '';
        html += ``;
        sortedCols.forEach(c => html += ``);
        html += '';

        // 構建數據行
        sortedRows.forEach(rv => {
            html += ``;
            sortedCols.forEach(cv => {
                const val = rows[rv][cv];
                html += ``;
            });
            html += '';
        });
        html += '
${this.rowKey}${c}
${this.dateFormat(rv)}${val !== undefined ? val : this.missingCell}
'; return html; } } // 使用範例:求同一天同 XMID 的 SZH 平均值 const pivot = new DataPivot({ aggregator: (a, b) => (a + b) / 2, // 平均值聚合 missingCell: '-' // 空值顯示 }); document.body.innerHTML = pivot.transform(json.Table1);

效能優化建議

  1. 虛擬滾動:數據超過 1000 行時,使用 react-window 或原生 IntersectionObserver 實現
  2. Web Worker:大數據樞紐計算移至背景執行緒,避免阻塞主執行緒
  3. 增量渲染:分批次 appendChild,配合 requestIdleCallback
  4. 記憶化:相同輸入緩存結果,避免重複計算

常見陷阱

  • 日期排序:ISO 字串可直接字典序排序,但需確保格式統一(如皆為 YYYY-MM-DD)
  • 數值精度:JS 浮點運算可能產生 0.1 + 0.2 = 0.30000000000000004,顯示時用 toFixed(2) 或 Intl.NumberFormat
  • XSS 風險:若數據來自用戶輸入,務必對單元格內容進行 HTML 轉義

總結

JSON 長表轉寬表的核心是「分組 → 聚合 → 矩陣化」。掌握通用的樞紐演算法,配合配置化聚合策略、排序規則、格式化函數,即可優雅處理各類報表數據轉換需求,遠勝硬編碼特定字段的一次性代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved