[英]Average of HTML table content column and row in JavaScript
所以我遇到了這個問題,我需要每列的平均值和每行如下:
7 9 8
5 7 9
6 6 8
至:
7 9 8 8
5 7 9 7
6 6 8 6.7
6 7.3 8.3
這是我到目前為止所做的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table id="myTable">
<tr>
<td>7</td>
<td>9</td>
<td>8</td>
</tr>
<tr>
<td>5</td>
<td>7</td>
<td>9</td>
</tr>
<tr>
<td>6</td>
<td>6</td>
<td>8</td>
</tr>
</table>
<script src="script.js"></script>
</body>
</html>
在scipt.js
里面:
(function () {
var table=document.getElementById("myTable");
var sum=0;
var row=table.rows;
console.log(row[0].innerText.split(" "));
var tr = document.createElement('tr');
for(var i=0, row; row.length>i; i++) {
sum = sum + parseInt(table.rows[i].cells[0].innerHTML);
}
tr.insertCell(0).textContent = sum / 3;
table.appendChild(tr);
})();
我是JavaScript的新手。 有沒有更好的方法來實現這種影響?
您可以使用嵌套for
循環。 創建一個填充0
的數組,為for
循環中的每個索引設置值,按照設置行的平均值設置總和和平均垂直列。 請注意,在最后一排的細胞,包括平均數的平均值,調整len
到len = cols.length
,即去掉-1
在len = cols.length -1
最后for
循環。
(function() { var table = document.getElementById("myTable"); var row = table.rows; // store columns sums var cols = Array.from({length: row.length + 1}, () => 0); for (var i = 0; row.length > i; i++) { var td = document.createElement('td'); var sum = 0; for (var j = n = 0; j < row[i].cells.length; sum += n, cols[j] += n, j++) { n = +(row[i].cells[j].innerHTML); } row[i].insertCell(j) .innerHTML = "<b>" + (sum / row.length).toFixed(1) + "</b>"; // set column values cols[cols.length - 1] += (sum / row.length -1); } // set column averages table.insertRow(); var lastrow = table.rows[table.rows.length - 1]; // set `len` to `len = cols.length` to include average of averages for (var i = 0, len = cols.length - 1; i < len; i++) { var td = document.createElement('td'); var html = "<b>" + (cols[i] / len).toFixed(1) + "</b>"; td.innerHTML = html; lastrow.appendChild(td); } })();
<table id="myTable"> <tr> <td>7</td> <td>9</td> <td>8</td> </tr> <tr> <td>5</td> <td>7</td> <td>9</td> </tr> <tr> <td>6</td> <td>6</td> <td>8</td> </tr> </table>
此代碼適用於水平計算平均值。 這是一個如何使用for
循環遍歷HTML
元素,將其內容作為字符串進行迭代並將其轉換為ints
的示例。
var table=document.getElementById("myTable");
var rows=table.rows;
for(var i = 0; i < rows.length; i++){
var cells = rows[i].cells;
var sum = 0;
for(var x = 0; x < cells.length; x++){
var cell = cells[x];
sum += parseInt(cell.innerHTML);
}
var average = sum/cells.length;
rows[i].innerHTML += "<td>"+average+"</td>";
}
您可以使用parseFloat((sum/3).toFixed(1))
來舍入總和:
var table = document.getElementById("myTable"); var rows = table.rows; var myTable2 = document.getElementById("myTable2"); var newRows = ''; for (let i = 0; i < rows.length ; i++ ){ let numbers = rows[i].cells; //console.log(numbers[0]innerHTML); newRows += "<tr>"; let sum = 0; for (let j = 0 ; j < numbers.length ; j++){ sum += parseInt(numbers[j].innerHTML); newRows += "<td>" + numbers[j].innerHTML + "</td>"; }; newRows += "<td><b>" + parseFloat((sum/3).toFixed(1)) + "</b></td></tr>"; }; //console.log(newRows); myTable2.innerHTML = newRows;
<table border="1" id="myTable"> <tr> <td>7</td> <td>9</td> <td>8</td> </tr> <tr> <td>5</td> <td>7</td> <td>9</td> </tr> <tr> <td>6</td> <td>6</td> <td>8</td> </tr> <table> <table border="1" id="myTable2"> </table>
一種方法如下:
// assigning the result of the immediately-invoked function expression
// (IIFE), the format of - among others - (function(){})()
// the final parentheses allow us to pass an argument to the enclosed
// function, to the 'averageTables' variable for subsequent use if
// required:
let averageTables = (function(opts) {
/* the 'opts' Object passed as the argument is as follows:
{
// String: the CSS selector to identify the relevant
// <table> elements:
'table': '#myTable, #myOtherStrangelyIdenticalTable',
// Boolean: whether or not you want to see the last cell
// in the <table> the average of the averages column
'hideAverageOfAverages': false,
// String: the class-name to add to the <td> containing
// the average of each <tr>:
'rowAverageClassName': 'rowAverage',
// String: the class-name to add to the <td> containing
// the average of each column:
'columnAverageClassName': 'columnAverage',
// String: the class-name to add to the <td> containing
// the average of the column of averages:
'averageOfAveragesClassName': 'averageOfAverage',
// Number: the number of decimal places to which the
// averages should be rounded:
'decimalPlaces': 1
}
*/
// here we use document.querySelectorAll() to retrieve the relevant
// <table> elements, assuming that the opts.table selector results
// in a selection of <table> elements:
let tableElements = document.querySelectorAll(opts.table),
// we use Array.from() to convert the NodeList from
// document.querySelectorAll() into an Array:
allTables = Array.from(tableElements),
// here we create a new <td> element:
newCell = document.createElement('td'),
// here we find the divisor, and multiplier, for
// accurately (insofar as JavaScript can) round
// to a set number of decimal places:
nDecimals = Math.pow(10, opts.decimalPlaces),
// and initialise some empty variables for later
// use:
rows, column, cell, average;
// here we use the Element.classList interface to add
// the class-name passed in from the opts Object:
newCell.classList.add(opts.rowAverageClassName);
// we iterate over the Array of <table> elements using
// Array.prototype.forEach():
allTables.forEach(function(table) {
// 'table' is a reference to the current <table> of the
// Array of <table> elements over which we're iterating.
// we cache the <tr> elements, as an Array, recovered
// from the HTMLTableElement.rows collection:
rows = Array.from(table.rows);
// iterating over that Array of <tr> elements:
rows.forEach(function(row) {
// 'row' is a reference to the current <tr> element
// from the Array of <tr> elements over which we're
// iterating.
// here we use Array.from() to create an Array of the
// <td> elements that are the element-children of the
// current <tr> element:
average = Array.from(row.children)
// we then use Array.prototype.reduce() to reduce
// that Array to a single element:
.reduce(function(value, currentCell) {
// 'value': the current value of the reduce method,
// (initialised to 0 as the final argument following
// the anonymous function),
// currentCell: the current <td> element of the
// Array of <td> elements over which we're iterating.
// here we add the currently-held value to the result
// of retrieving the text-content of the current <td>,
// and using String.prototype.trim() to remove any
// leading or trailing white-space, and then passing
// that resultant String to parseFloat() to convert
// a numeric String to a number (if possible); note
// that there are no sanity checks, so if the text
// cannot be converted to a Number then the result of
// reduce() will be either undefined or NaN.
// This approach, obviously finds the sum of the text
// of all <td> elements:
return value + parseFloat(currentCell.textContent.trim());
// following the summation, then, we divide it by the number
// of <td> elements within the <tr> to find the average:
}, 0) / row.children.length;
// we clone the created <td> element:
cell = newCell.cloneNode();
// and set its text-content to the result of the following,
// in which we multiply the found average by the value of
// nDecimals, and use Math.round() on the result, and then
// divide by the result of nDecimals to find the result to
// the user-defined number of decimal places (using
// Number.toFixed(n) will simply cut off the number without
// rounding, which is possibly not a big issue in your use-case):
cell.textContent = Math.round(average * nDecimals ) / nDecimals ;
// here we append the created, cloned <td> to the current <tr>:
row.appendChild(cell);
});
// here we simply find the last <tr> element in the <table>,
// and then clone that node, including its children, using
// cloneNode(true); it's worth remembering that
// document.querySelector() returns only a single node, if any,
// which is the first element it finds that matches the supplied
// CSS selector:
let newRow = table.querySelector('tr:last-child').cloneNode(true);
// here we use Array.from() to convert the NodeList of newRow.children
// into an Array, and then use Array.prototype.forEach() to iterate
// over that Array:
Array.from(newRow.children).forEach(function(cell, index) {
// 'cell': a reference to the current <td> element of the
// Array of <td> elements over which we're iterating,
// 'index': the index of the current <td> within the Array
// over which we're iterating.
// retrieving a collection of <td> elements using the CSS
// td:nth-child(), and interpolating the result of 'index + 1'
// as the argument to :nth-child(); we add 1 to the index
// because JavaScript is zero-based, whereas CSS is one-based; and
// then using Array.from() to convert that collection into
// an Array:
column = Array.from(table.querySelectorAll('td:nth-child(' + (index + 1) + ')'));
// here we calculate the average exactly the same way as above,
// but over the columns rather than the rows:
average = column.reduce(function(value, currentCell) {
return value + parseFloat(currentCell.textContent.trim());
}, 0) / column.length;
// we set the cell's text-content exactly the same way
// as above (which in DRY terms is, admittedly, ridiculous):
cell.textContent = Math.round(average * 10) / 10;
// here we add the user-supplied class-name to the
// column-average <td> elements:
cell.classList.add(opts.columnAverageClassName);
});
// and we then append the newRow to the current <table>
// element:
table.appendChild(newRow);
// here we find the :last-child of the newly-added row,
// which is the <td> containing the average of the
// averages column:
let averageOfAverage = newRow.querySelector('td:last-child');
// here we set the display of that <td>, if the user wants to
// hide the cell (opts.hideAverageOfAverages is true) then
// we set the display style to 'none'; otherwise (if
// opts.hideAverageOfAverages is anything other than exactly true)
// we set the display to that of 'table-cell':
averageOfAverage.style.display = opts.hideAverageOfAverages === true ? 'none' : 'table-cell';
// and then we add the requisite, user-defined, class-name:
averageOfAverage.classList.add(opts.averageOfAveragesClassName);
});
// at this point we return the Array of <tables> found
// to the calling context if the user wants to have
// use to them for any other reason:
return allTables;
})({
'table': '#myTable, #myOtherStrangelyIdenticalTable',
'hideAverageOfAverages': false,
'rowAverageClassName': 'rowAverage',
'columnAverageClassName': 'columnAverage',
'averageOfAveragesClassName': 'averageOfAverage',
'decimalPlaces': 1
});
let averageTables = (function(opts) { let tableElements = document.querySelectorAll(opts.table), allTables = Array.from(tableElements), newCell = document.createElement('td'), nDecimals = Math.pow(10, opts.decimalPlaces), rows, column, cell, average; newCell.classList.add(opts.rowAverageClassName); allTables.forEach(function(table) { rows = Array.from(table.rows); rows.forEach(function(row) { average = Array.from(row.children).reduce(function(value, currentCell) { return value + parseFloat(currentCell.textContent.trim()); }, 0) / row.children.length; cell = newCell.cloneNode(); cell.textContent = Math.round(average * nDecimals) / nDecimals; row.appendChild(cell); }); let newRow = table.querySelector('tr:last-child').cloneNode(true); Array.from(newRow.children).forEach(function(cell, index, all) { column = Array.from(table.querySelectorAll('td:nth-child(' + (index + 1) + ')')); average = column.reduce(function(value, currentCell) { return value + parseFloat(currentCell.textContent.trim()); }, 0) / column.length; cell.textContent = Math.round(average * nDecimals) / nDecimals; cell.classList.add(opts.columnAverageClassName); }); table.appendChild(newRow); let averageOfAverage = newRow.querySelector('td:last-child'); averageOfAverage.style.display = opts.hideAverageOfAverages === true ? 'none' : 'table-cell'; averageOfAverage.classList.add(opts.averageOfAveragesClassName); }); return Array.from(document.querySelectorAll(opts.table)); })({ 'table': '#myTable, #myOtherStrangelyIdenticalTable', 'hideAverageOfAverages': false, 'rowAverageClassName': 'rowAverage', 'columnAverageClassName': 'columnAverage', 'averageOfAveragesClassName': 'averageOfAverage', 'decimalPlaces': 1 });
table { margin: 0 auto 1em auto; } td { width: 1.5em; height: 1.5em; border: 1px solid #000; text-align: center; } td.rowAverage { color: red; } td.columnAverage { color: limegreen; } td.columnAverage.rowAverage.averageOfAverage { color: rebeccapurple; font-weight: bold; }
<table id="myTable"> <tr> <td>7</td> <td>9</td> <td>8</td> </tr> <tr> <td>5</td> <td>7</td> <td>9</td> </tr> <tr> <td>6</td> <td>6</td> <td>8</td> </tr> </table> <table id="myOtherStrangelyIdenticalTable"> <tr> <td>7</td> <td>9</td> <td>8</td> </tr> <tr> <td>5</td> <td>7</td> <td>9</td> </tr> <tr> <td>6</td> <td>6</td> <td>8</td> </tr> </table>
JS小提琴演示 。
參考文獻:
Array.from()
。 Array.prototype.forEach()
。 Array.prototype.reduce()
。 expression ? ifTrue : ifFalse
) 。 document.createElement()
。 document.querySelector()
。 document.querySelectorAll()
。 Element.classList
。 HTMLElement.style
。 HTMLTableElement
。 HTMLTableElement.rows
。 Math.pow()
。 Math.round()
。 Node.appendChild()
。 Node.cloneNode()
。 Node.textContent
。 parentNode.children
。 parseFloat()
。 String.prototype.trim()
。 您可以執行此操作,迭代行並首先填充最后一列。
更新行的平均列后,迭代第n列並更新平均值。
這是一個示例:
document.onreadystatechange = () => { if (document.readyState === 'complete') { var rows = document.querySelector("#myTable").rows; [].forEach.call(rows, (row) => { let currentSum = 0; let cells = row.cells; [].forEach.call(cells, (currentVal) => { currentSum += parseInt(currentVal.innerText, 10); }); appendElement(row, (currentSum / cells.length).toFixed(1)); }); let columnCount = document.querySelectorAll("tr:nth-child(1)>td").length; let rowContent = document.createElement("tr"); let table = document.querySelector("#myTable"); for (let idx = 0; idx < columnCount; idx++) { let columns = document.querySelectorAll("tr>td:nth-child(" + (idx + 1) + ")"); let currentSum = 0; [].forEach.call(columns, (column) => { currentSum += parseInt(column.innerText, 10); }); appendElement(rowContent, (currentSum / rows.length).toFixed(1)) } table.appendChild(rowContent); } }; function appendElement(parent, sum) { let cellEle = document.createElement("td"); cellEle.innerText = sum; cellEle.classList.add("bold"); parent.appendChild(cellEle); }
.bold { font-weight: bold; }
<table id="myTable"> <tr> <td>7</td> <td>9</td> <td>8</td> </tr> <tr> <td>5</td> <td>7</td> <td>9</td> </tr> <tr> <td>6</td> <td>6</td> <td>8</td> </tr> </table>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.