javascript - 根据前 3 列对 JSON 数据进行分组,并对 HTML/JS 中第 4 列的编号进行求和

标签 javascript jquery html json

我有一个 JSON 文件,我想根据 JSON 对象中的值组合创建多个 HTML 表。

让我们看一下 JSON 示例以提供更好的解释:

var data = {"headers":["plat","chan","cat","num"],"rows":[["plat1","chan1","cat1",1],
["plat1","chan1","cat1",2],["plat2","chan1","cat2",5]]};

在上面的示例中,我们有 2 行的前三列具有相同的值。我想生成一个包含一行的 HTML 表(因为值相同),但第四列必须有 SUM。

因此,HTML 表格必须类似于: plat1、chan1、cat1、3 plat2、chan1、cat2、5

下面的代码片段基于初始脚本和其他 stackoverflow 用户的帮助:)

var data = {"headers":["plat","chan","group","cat","num"],"rows":[["plat1","chan1","bbb","cat1",222],
["plat1","chan1","bbb","cat1",333],
["plat1","chan1","bbb","cat2",850]]};

// transform the data to get a clear connection between the
// heading and the corresponding data
const transformedData = data.rows.map((row) => {
	const emptyRowDataObject = {};
	return row.reduce((dataObjSoFar, rowData, rowDataIndex) => {
  	// for each of the values in the row, add a property
    // with the name of the corresponding header
    const correspondingHeader = data.headers[rowDataIndex];
  	dataObjSoFar[correspondingHeader] = rowData;
    return dataObjSoFar;
  }, emptyRowDataObject);
});

const headersOfInterest = ['plat','chan','cat','num'];
printTable(headersOfInterest, transformedData);


function printTable(headers, rowDataWithHeaders) {
	let tableHeader = createTableHeaders(headers);
  let tableRows = rowDataWithHeaders.map(row => createTableRow(headers, row));
  let table = `<table>${ tableHeader }<tbody>${ tableRows }</tbody></table>`;
  $("#one").html(table);
}

function createTableHeaders(headers) {
	let headersHTML = '<thead><tr>';
	headers.forEach(header => {
  	headersHTML += `<th>${ header }</th>`;
  });
  headersHTML += '</tr></thead>';
  return headersHTML;
}

function createTableRow(headers, dataRow) {
	let tr = '<tr>';
  // go through all the headers we are interested in
  // and get the corresponding value from this data row
  headers.forEach(header => {
  	tr += `<td>${ dataRow[header] }</td>`;
  });
  tr += '</tr>';
  return tr;
}

function getSumOfValuesInColumn(headerName, rowDataWithHeaders) {
	// this could be done with Array.reduce as well
  let sum = 0;
	for(let i = 0; i < rowDataWithHeaders.length; i++) {
  	sum += rowDataWithHeaders[i][headerName]
  }
  return sum;
}

function printSummationTable(headersToSum, dataRows) {
	const tableHeader = createTableHeaders(headersToSum);
  const sumData = {};
  headersToSum.forEach(header => {
  	sumData[header] = getSumOfValuesInColumn(header, dataRows);
  });
  // treat sumData as a single table row
  const tableRows = createTableRow(headersToSum, sumData);
  let table = `<table>${ tableHeader }<tbody>${ tableRows }</tbody></table>`;
  $("#two").html(table);
}

const headersToSum = ['plat','chan','cat','num'];
printSummationTable(headersToSum, transformedData);


  
@import url('https://fonts.googleapis.com/css?family=Roboto');

body { 
    margin: 0;
    color:#fff;
    font-family: Roboto; }
.row {
    display: table;
    width: 100%;
    height: 241px; 
    background-color:#454545;
}
.row > .col-lg-6 {
    display: table-cell;
    vertical-align: middle;
}
.container {
  /*display: flex;*/
  flex-wrap: wrap;
}
.container > div {
  padding: 15px;
  margin: 5px;
  flex: 0 0 calc(100% - 20px);
  text-align: left;
}

/*img {
    padding-left: 7%;
    max-height:55px;
    width:auto;
}*/
td{
  padding: 2px 2px;
  text-align: center;
  margin: 6px 0;
  border: none;
}
table{
  width: 100%;
  background-color:#454545;
  font-weight:500;
  border-collapse: separate;
  border-spacing:0.3em 1.1em;
  color: #fff;
  border: 0;
}
tr{
    font-size: 1.5em;
    text-transform:capitalize;
}
tr:nth-child(1) {
    color: #CCC;
    font-size: 1.5em;
 	}
	
#one,#two,#three,#four{
    padding-top:2%;
 	}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h4 style="color:#000;">Table before summing the number for the rows that have the same value in the first three columns</h4>
<div id="one"></div>
<h4 style="color:#000;">Table where we can see the SUM but for all the rows. The first three columns are a concatenation of the values which should not happen.</h4>
<div id="two"></div>
<h4 style="color:#000;">Table that I want to get (static)</h4>
<div><table> <thead> <tr> <th>plat</th> <th>chan</th> <th>cat</th> <th>num</th> </tr></thead> <tbody> <tr> <td>plat1</td><td>chan1</td><td>cat1</td><td>555</td></tr><tr> <td>plat1</td><td>chan1</td><td>cat2</td><td>850</td></tr></tbody></table></div>

最佳答案

我创建了以下答案,希望它能满足您的需求。

var data = {
  "headers":["plat","chan","group","cat","num"],
  "rows":[  
    ["plat1","chan1","bbb","cat1",222],
    ["plat1","chan1","bbb","cat1",333],
    ["plat1","chan1","bbb","cat2",850]
  ]
};


function transformData(rows) {
  const 
    rowMap = new Map(),
    result = [];
    
  // Iterate over the rows.
  rows.forEach(row => {
    const
      // Create a key, it is the first 4 elements joined together.
      key = row.slice(0,4).join();
      
    // Check if the Map has the generated key...
    if (rowMap.has(key)) {
      // The map has the key, we need to add up the values
      const
        // Get the value for the current key.
        storedRow = rowMap.get(key);
        // Add the value of the current row to the row in the map.
        storedRow[4] += row[4];
    } else {
      // The key doens't exist yet, add the row to the map.
      rowMap.set(key, row);
    }
  });
  
  // Iterate over all the entries in the map and push each value with the
  // summed up value into the array.
  rowMap.forEach(value => {
    result.push(value);
  });
    
  // Return the array.
  return result;   
}

// Creates cells for all items in the row array. When no cell type is set
// the method will create td elements.
function getCells(row, element = 'td') {
  // Reduce the array to a single string.
  return row.reduce((result, cell) => {
    result += `<${element}>${cell}</${element}>`;
    
    return result;
  }, '');
}

// Creates tr elements for each item in the rows array, each tr element
// will be filled with td elements.
function getBody(rows) {
  // Reduce the array to a single string.
  return rows.reduce((result, row) => {
    result += `<tr>${getCells(row)}</tr>`
    
    return result;
  }, '');
}

// Create the HTML table.
function createTable(tableData) {
  let
    tableHTML = '';
    
  tableHTML = `<table>
    <thead><tr>${getCells(tableData.headers, 'th')}</tr></thead>
    <tbody>${getBody(tableData.rows)}</tbody>
  </table>`;
  
  return tableHTML;
}


data.rows = transformData(data.rows);
const
  generateHTML = createTable(data);
$("#two").html(generateHTML);
@import url('https://fonts.googleapis.com/css?family=Roboto');

body { 
    margin: 0;
    color:#fff;
    font-family: Roboto; }
.row {
    display: table;
    width: 100%;
    height: 241px; 
    background-color:#454545;
}
.row > .col-lg-6 {
    display: table-cell;
    vertical-align: middle;
}
.container {
  /*display: flex;*/
  flex-wrap: wrap;
}
.container > div {
  padding: 15px;
  margin: 5px;
  flex: 0 0 calc(100% - 20px);
  text-align: left;
}

/*img {
    padding-left: 7%;
    max-height:55px;
    width:auto;
}*/
td{
  padding: 2px 2px;
  text-align: center;
  margin: 6px 0;
  border: none;
}
table{
  width: 100%;
  background-color:#454545;
  font-weight:500;
  border-collapse: separate;
  border-spacing:0.3em 1.1em;
  color: #fff;
  border: 0;
}
tr{
    font-size: 1.5em;
    text-transform:capitalize;
}
tr:nth-child(1) {
    color: #CCC;
    font-size: 1.5em;
 	}
	
#one,#two,#three,#four{
    padding-top:2%;
 	}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h4 style="color:#000;">Result table (dynamic).</h4>
<div id="two"></div>

<h4 style="color:#000;">Table that I want to get (static)</h4>
<div><table> <thead> <tr> <th>plat</th> <th>chan</th> <th>cat</th> <th>num</th> </tr></thead> <tbody> <tr> <td>plat1</td><td>chan1</td><td>cat1</td><td>555</td></tr><tr> <td>plat1</td><td>chan1</td><td>cat2</td><td>850</td></tr></tbody></table></div>

关于javascript - 根据前 3 列对 JSON 数据进行分组,并对 HTML/JS 中第 4 列的编号进行求和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46026882/

相关文章:

javascript - 如何获取开始标签内的文本并在jquery中进行更改?

javascript - 一个隐藏输入 vs 1000 个隐藏输入?

html - bootstrap 3 不应用 panel-primary 作为蓝色背景色

javascript - 如何从下拉元素中查找并清除所有选定的值

javascript - 如何将 Javascript 语法中的正则表达式转换为 .NET 语法

javascript - 在 jquery 的帮助下选择下拉菜单的值

javascript - CSS Submit Button with Loading Animation 有悬停效果划分

html - 在 Ionic 5 中更改 ion-searchbar 输入的字体大小

javascript - 如何通过 AJAX 解析和使用 HTML 和变量?

javascript - 如何将时间轴中的第二个 Greensock 动画更改为提前 1 秒开始