使用每个数据组的唯一 header 行组织 HTML table 中的 JSON 数据
Organize JSON data in HTML table with unique header rows for each data group
我有一个 JSON object,其中包括一个 key:value 对 callRoot。此 key:value 对的示例值包括 @S、@C 和 @W .有多个 object 具有相同的值,我希望在每个分组的开头设置一个 HTML table 标题行,并为每组数据重复它。
更新
获取 API 函数以访问远程 API 数据:
const fetchData = function() {
const apiKey = "";
const request = `https://apiurl.com`;
fetch(request)
.then(response => response.json())
.then((data) => foo(data))
.catch(error => {
console.log(error);
});
}
fetchData();
更新二
for (let i of filtered[property]) {
const tr = document.createElement('tr');
tblBody.appendChild(tr);
data.forEach(element => {
console.log(element);
});
示例 JSON 数据:
const data = [
{
"symbol": {
"description": "SOYBEANS January 2022"
},
"actualSymbol": "@SF22",
"high": {
"number": 1396
},
"low": {
"number": 1374.75
},
"close": null,
"settlePrice": {
"number": 1401.5
},
"last": {
"number": 1378
},
"change": {
"number": -23.5
},
"month": "Jan 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "SOYBEANS March 2022"
},
"actualSymbol": "@SH22",
"high": {
"number": 1409.75
},
"low": {
"number": 1379
},
"close": null,
"settlePrice": {
"number": 1410.25
},
"last": {
"number": 1383.25
},
"change": {
"number": -27
},
"month": "Mar 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "SOYBEANS May 2022",
},
"actualSymbol": "@SK22",
"high": {
"number": 1418
},
"low": {
"number": 1387.5
},
"close": null,
"settlePrice": {
"number": 1418.75
},
"last": {
"number": 1391.25
},
"change": {
"number": -27.5
},
"month": "May 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "CORN March 2022",
},
"actualSymbol": "@CH22",
"high": {
"number": 608
},
"low": {
"number": 596.75
},
"close": null,
"settlePrice": {
"number": 606.75
},
"last": {
"number": 599.25
},
"change": {
"number": -7.5
},
"month": "Mar 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "CORN May 2022",
},
"actualSymbol": "@CK22",
"high": {
"number": 608.5
},
"low": {
"number": 598.25
},
"close": null,
"settlePrice": {
"number": 607.75
},
"last": {
"number": 600.75
},
"change": {
"number": -7
},
"month": "May 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "CORN July 2022",
},
"actualSymbol": "@CN22",
"high": {
"number": 605.25
},
"low": {
"number": 595.5
},
"close": null,
"settlePrice": {
"number": 604.5
},
"last": {
"number": 598
},
"change": {
"number": -6.5
},
"month": "Jul 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "WHEAT March 2022",
},
"actualSymbol": "@WH22",
"high": {
"number": 767.5
},
"low": {
"number": 748
},
"close": null,
"settlePrice": {
"number": 758.5
},
"last": {
"number": 763.75
},
"change": {
"number": 5.25
},
"month": "Mar 22",
"callRoot": "@W",
"userDescription": "WHEAT",
},
{
"symbol": {
"description": "WHEAT May 2022",
},
"actualSymbol": "@WK22",
"high": {
"number": 768.5
},
"low": {
"number": 750
},
"close": null,
"settlePrice": {
"number": 760.5
},
"last": {
"number": 765.5
},
"change": {
"number": 5
},
"month": "May 22",
"callRoot": "@W",
"userDescription": "WHEAT",
},
{
"symbol": {
"description": "WHEAT July 2022",
},
"actualSymbol": "@WN22",
"high": {
"number": 763.25
},
"low": {
"number": 747.25
},
"close": null,
"settlePrice": {
"number": 757
},
"last": {
"number": 760.5
},
"change": {
"number": 3.5
},
"month": "Jul 22",
"callRoot": "@W",
"userDescription": "WHEAT",
}
];
这是我一直在玩的一些代码,尽管我可能无法实现我的设定要求。 switch 语句可能比 if/else if statement
更适合
// Create empty arrays for each callRoot grouping
const soybeans = [];
const corn = [];
const wheat = [];
for(let commodity of commodities) {
let callRoot = commodity.callRoot;
if(callRoot.includes("@S")) {
} else if(callRoot.includes("@C")) {
} else if(callRoot.includes("@W")) {
}
}
const soyHeader = soybean[0];
if(soyHeader) {
// Render table header row HTML
}
// Render table row HTML
const cornHeader = corn[0];
if(cornHeader) {
// Render table header row HTML
}
// Render table row HTML
const wheatHeader = wheat[0];
if(wheatHeader) {
// Render table header row HTML
}
// Render table row HTML
示例HTML table结构:
<table>
<tbody>
<tr>
<th colspan="9">SOYBEANS</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">CORN</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">WHEAT</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
</table>
我试图创建一个函数,它根据你的示例table创建了
这是我的 script/function:
旧函数数据错误但输出正确.-.
const filterData = function (data) {
const filtered = {};
data.forEach(element => { // going through all the elements
if (filtered[element.callRoot]) filtered[element.callRoot].push(element); // if callRoot already exists in filtered object
else filtered[element.callRoot] = [element]; // else create property with callRoot as name -> here we push all the objects with the same callRoot name
})
return filtered;
};
const foo = function (data, element) {
const filtered = filterData(data);
// starting to create Table
// creating static table element, here becomes the element argument useful
const table = document.createElement('table');
element.appendChild(table);
// now we start creating the tbodies, trs and tds with the filtered data
// so we go through our filtered object by looping through an array of the keys ('@S','@C','@W')
Object.keys(filtered).forEach(property => {
// for each property we will create the tbody and tr + th and append them
const tbody = document.createElement('tbody');
table.appendChild(tbody);
let tr = document.createElement('tr');
tbody.appendChild(tr);
const th = document.createElement('th');
th.setAttribute('colspan', 9); // adding colspan attribute
th.textContent = filtered[property][0].userDescription; // taking the description as th text
tr.appendChild(th);
// now we create the rest of the tbody
// since i dont know where the data for the table comes from i will use the defined data from your example html output
// creating tr for our header tds
tr = document.createElement('tr');
tbody.appendChild(tr);
const definedDataArrayHeaders = ['Month', 'Last', 'Change', 'High', 'Low']; // headers from your example
definedDataArrayHeaders.forEach(element => { // going through the headers
const td = document.createElement('td');
td.textContent = element; // writing the header inside the td
tr.appendChild(td);
});
const definedDataArrayTds = ['August 2022', "1265'2", "-2'4", "1275'2", "1261'4"]; // tds from your example
for (let i of filtered[property]) { // will loop through each object inside our filtered array -> each tr in our future table
const tr = document.createElement('tr'); // creating tr for each data
tbody.appendChild(tr);
definedDataArrayTds.forEach(element => { // looping through the td data
const td = document.createElement('td');
td.textContent = element; // writing the data inside the td
tr.appendChild(td);
})
}
})
}
foo(commodities, document.querySelector('div')); // calling the function with data and Element where the table should be appended to
FALSE 旧使用数据:
const commodities = [
{
actualSymbol: "@SF22",
callRoot: "@S",
open: 1.00,
close: 2.00,
userDescription: "SOYBEANS",
// Other data
},
{
actualSymbol: "@SH22",
callRoot: "@S",
open: 4.00,
close: 6.00,
userDescription: "SOYBEANS",
// Other data
},
{
actualSymbol: "@SK22",
callRoot: "@S",
open: 0.50,
close: 2.30,
userDescription: "SOYBEANS",
// Other data
},
{
actualSymbol: "@CH22",
callRoot: "@C",
open: 0.25,
close: 0.75,
userDescription: "CORN",
// Other data
},
{
actualSymbol: "@CK22",
callRoot: "@C",
open: 5.00,
close: 6.75,
userDescription: "CORN",
// Other data
},
{
actualSymbol: "@CN22",
callRoot: "@C",
open: 1.00,
close: 2.00,
userDescription: "CORN",
// Other data
},
{
actualSymbol: "@WH22",
callRoot: "@W",
open: 3.25,
close: 2.00,
userDescription: "WHEAT",
// Other data
},
{
actualSymbol: "@WK22",
callRoot: "@W",
open: 1.00,
close: 2.00,
userDescription: "WHEAT",
// Other data
},
{
actualSymbol: "@WN22",
callRoot: "@W",
open: 0.10,
close: 0.20,
userDescription: "WHEAT",
// Other data
}
];
但是对于正确的示例输出,这是 html 输出:
<div>
<table>
<tbody>
<tr>
<th colspan="9">SOYBEANS</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">CORN</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">WHEAT</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
</table>
</div>
新解决方案,希望这个能正常工作哈哈
这里是新版的脚本,肯定不好,就当是自己的攻略吧
const filterData2 = function (data) {
const filtered = {};
const wantedData = ['month', 'change', 'last', 'high', 'low', 'settlePrice'];
data.forEach(element => { // going through all the elements
// now using userDescript as key since its a bit more precise
if (filtered[element.userDescription]) { // if userDescription already exists in filtered object
const piece = [];
// now we extract only the data we need for our html table:
Object.entries(element).forEach(array => {
if (wantedData.includes(array[0])) array[1]?.number ? piece.push([array[0], array[1].number]) : piece.push([array[0], array[1]]);
});
filtered[element.userDescription].push(piece);
}
else {// else create property with userDescription as name -> here we push all the objects with the same callRoot name
const piece = [];
filtered[element.userDescription] = [];
Object.entries(element).forEach(array => {
if (wantedData.includes(array[0])) array[1]?.number ? piece.push([array[0], array[1].number]) : piece.push([array[0], array[1]]);
});
filtered[element.userDescription].push(piece);
}
})
return filtered;
};
// needed since i structured my filtered data different
const getValue = (arr, string) => arr.find(pair => pair[0] === string);
const foo2 = function (data, element) {
const filtered = filterData2(data);
// starting to create Table
// creating static table element, here becomes the element argument useful
const table = document.createElement('table');
element.appendChild(table);
// now we start creating the tbodies, trs and tds with the filtered data
// so we go through our filtered object by looping through an array of the keys in example:('SOYBEANS','CORN','WHEAT')
Object.keys(filtered).forEach(key => {
// key will be either 'SOYBEANS', 'CORN', 'WHEAT' - in this example in exactly this order
// for each key we will create the tbody and tr + th and append them
const tbody = document.createElement('tbody');
table.appendChild(tbody);
let tr = document.createElement('tr'); // using let here since we are going to overwrite this variable later so we dont have to create a new one
tbody.appendChild(tr);
const th = document.createElement('th');
th.setAttribute('colspan', 9); // adding colspan attribute
th.textContent = key; // taking the key as a header
tr.appendChild(th);
// now we create the rest of the tbody
// now since we filtered the data so in our filtered variable are only the necessary values for our table except the Settle Date
// creating tr for our header tds
tr = document.createElement('tr');
tbody.appendChild(tr);
const definedDataArrayHeaders = ['MONTH', 'LAST', 'CHANGE', 'HIGH', 'LOW', 'SETTLE DATE', 'SETTLE PRICE', 'MORE']; // Headers for the Table, can be anything - keep in Mind the date must be coming from somewhere for these headers, just some are covered by the filtered Array
definedDataArrayHeaders.forEach(header => { // going through the headers
const td = document.createElement('td');
td.textContent = header; // writing the header inside the td
tr.appendChild(td); // tr we created outside, so they all come into the same row
});
const definedDataArrayTds = ['month', "last", "change", "high", "low", "missing", "settlePrice", "missing"]; // this array must contain the names of the values inside the filtered array and must be in the same order as "definedDataArrayHeaders" so the data is in the right column
// since the Settle date and more value arent in the data/filtered array i will take placeholders so the table still renders right
// this part is needed to be changed a lot, since the data is now structured completely different
for (let i of filtered[key]) { // will loop through each object inside our filtered array -> each tr in our future table
const tr = document.createElement('tr'); // creating tr for each data
tbody.appendChild(tr);
definedDataArrayTds.forEach(element => { // looping through the td data
const td = document.createElement('td');
td.textContent = getValue(i, element)?.[1] || 'PLACEHOLDER'; // writing the data inside the td
tr.appendChild(td);
})
}
})
}
foo2(data, document.querySelector('div'));
此新示例中使用的数据:
const data = [
{
"symbol": {
"description": "SOYBEANS January 2022"
},
"actualSymbol": "@SF22",
"high": {
"number": 1396
},
"low": {
"number": 1374.75
},
"close": null,
"settlePrice": {
"number": 1401.5
},
"last": {
"number": 1378
},
"change": {
"number": -23.5
},
"month": "Jan 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "SOYBEANS March 2022"
},
"actualSymbol": "@SH22",
"high": {
"number": 1409.75
},
"low": {
"number": 1379
},
"close": null,
"settlePrice": {
"number": 1410.25
},
"last": {
"number": 1383.25
},
"change": {
"number": -27
},
"month": "Mar 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "SOYBEANS May 2022",
},
"actualSymbol": "@SK22",
"high": {
"number": 1418
},
"low": {
"number": 1387.5
},
"close": null,
"settlePrice": {
"number": 1418.75
},
"last": {
"number": 1391.25
},
"change": {
"number": -27.5
},
"month": "May 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "CORN March 2022",
},
"actualSymbol": "@CH22",
"high": {
"number": 608
},
"low": {
"number": 596.75
},
"close": null,
"settlePrice": {
"number": 606.75
},
"last": {
"number": 599.25
},
"change": {
"number": -7.5
},
"month": "Mar 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "CORN May 2022",
},
"actualSymbol": "@CK22",
"high": {
"number": 608.5
},
"low": {
"number": 598.25
},
"close": null,
"settlePrice": {
"number": 607.75
},
"last": {
"number": 600.75
},
"change": {
"number": -7
},
"month": "May 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "CORN July 2022",
},
"actualSymbol": "@CN22",
"high": {
"number": 605.25
},
"low": {
"number": 595.5
},
"close": null,
"settlePrice": {
"number": 604.5
},
"last": {
"number": 598
},
"change": {
"number": -6.5
},
"month": "Jul 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "WHEAT March 2022",
},
"actualSymbol": "@WH22",
"high": {
"number": 767.5
},
"low": {
"number": 748
},
"close": null,
"settlePrice": {
"number": 758.5
},
"last": {
"number": 763.75
},
"change": {
"number": 5.25
},
"month": "Mar 22",
"callRoot": "@W",
"userDescription": "WHEAT",
},
{
"symbol": {
"description": "WHEAT May 2022",
},
"actualSymbol": "@WK22",
"high": {
"number": 768.5
},
"low": {
"number": 750
},
"close": null,
"settlePrice": {
"number": 760.5
},
"last": {
"number": 765.5
},
"change": {
"number": 5
},
"month": "May 22",
"callRoot": "@W",
"userDescription": "WHEAT",
},
{
"symbol": {
"description": "WHEAT July 2022",
},
"actualSymbol": "@WN22",
"high": {
"number": 763.25
},
"low": {
"number": 747.25
},
"close": null,
"settlePrice": {
"number": 757
},
"last": {
"number": 760.5
},
"change": {
"number": 3.5
},
"month": "Jul 22",
"callRoot": "@W",
"userDescription": "WHEAT",
}
];
用上面的数据例子输出
<div>
<table>
<tbody>
<tr>
<th colspan="9">SOYBEANS</th>
</tr>
<tr>
<td>MONTH</td>
<td>LAST</td>
<td>CHANGE</td>
<td>HIGH</td>
<td>LOW</td>
<td>SETTLE DATE</td>
<td>SETTLE PRICE</td>
<td>MORE</td>
</tr>
<tr>
<td>Jan 22</td>
<td>1378</td>
<td>-23.5</td>
<td>1396</td>
<td>1374.75</td>
<td>PLACEHOLDER</td>
<td>1401.5</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>Mar 22</td>
<td>1383.25</td>
<td>-27</td>
<td>1409.75</td>
<td>1379</td>
<td>PLACEHOLDER</td>
<td>1410.25</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>May 22</td>
<td>1391.25</td>
<td>-27.5</td>
<td>1418</td>
<td>1387.5</td>
<td>PLACEHOLDER</td>
<td>1418.75</td>
<td>PLACEHOLDER</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">CORN</th>
</tr>
<tr>
<td>MONTH</td>
<td>LAST</td>
<td>CHANGE</td>
<td>HIGH</td>
<td>LOW</td>
<td>SETTLE DATE</td>
<td>SETTLE PRICE</td>
<td>MORE</td>
</tr>
<tr>
<td>Mar 22</td>
<td>599.25</td>
<td>-7.5</td>
<td>608</td>
<td>596.75</td>
<td>PLACEHOLDER</td>
<td>606.75</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>May 22</td>
<td>600.75</td>
<td>-7</td>
<td>608.5</td>
<td>598.25</td>
<td>PLACEHOLDER</td>
<td>607.75</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>Jul 22</td>
<td>598</td>
<td>-6.5</td>
<td>605.25</td>
<td>595.5</td>
<td>PLACEHOLDER</td>
<td>604.5</td>
<td>PLACEHOLDER</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">WHEAT</th>
</tr>
<tr>
<td>MONTH</td>
<td>LAST</td>
<td>CHANGE</td>
<td>HIGH</td>
<td>LOW</td>
<td>SETTLE DATE</td>
<td>SETTLE PRICE</td>
<td>MORE</td>
</tr>
<tr>
<td>Mar 22</td>
<td>763.75</td>
<td>5.25</td>
<td>767.5</td>
<td>748</td>
<td>PLACEHOLDER</td>
<td>758.5</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>May 22</td>
<td>765.5</td>
<td>5</td>
<td>768.5</td>
<td>750</td>
<td>PLACEHOLDER</td>
<td>760.5</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>Jul 22</td>
<td>760.5</td>
<td>3.5</td>
<td>763.25</td>
<td>747.25</td>
<td>PLACEHOLDER</td>
<td>757</td>
<td>PLACEHOLDER</td>
</tr>
</tbody>
</table>
</div>
我有一个 JSON object,其中包括一个 key:value 对 callRoot。此 key:value 对的示例值包括 @S、@C 和 @W .有多个 object 具有相同的值,我希望在每个分组的开头设置一个 HTML table 标题行,并为每组数据重复它。
更新
获取 API 函数以访问远程 API 数据:
const fetchData = function() {
const apiKey = "";
const request = `https://apiurl.com`;
fetch(request)
.then(response => response.json())
.then((data) => foo(data))
.catch(error => {
console.log(error);
});
}
fetchData();
更新二
for (let i of filtered[property]) {
const tr = document.createElement('tr');
tblBody.appendChild(tr);
data.forEach(element => {
console.log(element);
});
示例 JSON 数据:
const data = [
{
"symbol": {
"description": "SOYBEANS January 2022"
},
"actualSymbol": "@SF22",
"high": {
"number": 1396
},
"low": {
"number": 1374.75
},
"close": null,
"settlePrice": {
"number": 1401.5
},
"last": {
"number": 1378
},
"change": {
"number": -23.5
},
"month": "Jan 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "SOYBEANS March 2022"
},
"actualSymbol": "@SH22",
"high": {
"number": 1409.75
},
"low": {
"number": 1379
},
"close": null,
"settlePrice": {
"number": 1410.25
},
"last": {
"number": 1383.25
},
"change": {
"number": -27
},
"month": "Mar 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "SOYBEANS May 2022",
},
"actualSymbol": "@SK22",
"high": {
"number": 1418
},
"low": {
"number": 1387.5
},
"close": null,
"settlePrice": {
"number": 1418.75
},
"last": {
"number": 1391.25
},
"change": {
"number": -27.5
},
"month": "May 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "CORN March 2022",
},
"actualSymbol": "@CH22",
"high": {
"number": 608
},
"low": {
"number": 596.75
},
"close": null,
"settlePrice": {
"number": 606.75
},
"last": {
"number": 599.25
},
"change": {
"number": -7.5
},
"month": "Mar 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "CORN May 2022",
},
"actualSymbol": "@CK22",
"high": {
"number": 608.5
},
"low": {
"number": 598.25
},
"close": null,
"settlePrice": {
"number": 607.75
},
"last": {
"number": 600.75
},
"change": {
"number": -7
},
"month": "May 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "CORN July 2022",
},
"actualSymbol": "@CN22",
"high": {
"number": 605.25
},
"low": {
"number": 595.5
},
"close": null,
"settlePrice": {
"number": 604.5
},
"last": {
"number": 598
},
"change": {
"number": -6.5
},
"month": "Jul 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "WHEAT March 2022",
},
"actualSymbol": "@WH22",
"high": {
"number": 767.5
},
"low": {
"number": 748
},
"close": null,
"settlePrice": {
"number": 758.5
},
"last": {
"number": 763.75
},
"change": {
"number": 5.25
},
"month": "Mar 22",
"callRoot": "@W",
"userDescription": "WHEAT",
},
{
"symbol": {
"description": "WHEAT May 2022",
},
"actualSymbol": "@WK22",
"high": {
"number": 768.5
},
"low": {
"number": 750
},
"close": null,
"settlePrice": {
"number": 760.5
},
"last": {
"number": 765.5
},
"change": {
"number": 5
},
"month": "May 22",
"callRoot": "@W",
"userDescription": "WHEAT",
},
{
"symbol": {
"description": "WHEAT July 2022",
},
"actualSymbol": "@WN22",
"high": {
"number": 763.25
},
"low": {
"number": 747.25
},
"close": null,
"settlePrice": {
"number": 757
},
"last": {
"number": 760.5
},
"change": {
"number": 3.5
},
"month": "Jul 22",
"callRoot": "@W",
"userDescription": "WHEAT",
}
];
这是我一直在玩的一些代码,尽管我可能无法实现我的设定要求。 switch 语句可能比 if/else if statement
// Create empty arrays for each callRoot grouping
const soybeans = [];
const corn = [];
const wheat = [];
for(let commodity of commodities) {
let callRoot = commodity.callRoot;
if(callRoot.includes("@S")) {
} else if(callRoot.includes("@C")) {
} else if(callRoot.includes("@W")) {
}
}
const soyHeader = soybean[0];
if(soyHeader) {
// Render table header row HTML
}
// Render table row HTML
const cornHeader = corn[0];
if(cornHeader) {
// Render table header row HTML
}
// Render table row HTML
const wheatHeader = wheat[0];
if(wheatHeader) {
// Render table header row HTML
}
// Render table row HTML
示例HTML table结构:
<table>
<tbody>
<tr>
<th colspan="9">SOYBEANS</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">CORN</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">WHEAT</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
</table>
我试图创建一个函数,它根据你的示例table创建了
这是我的 script/function:
旧函数数据错误但输出正确.-.
const filterData = function (data) {
const filtered = {};
data.forEach(element => { // going through all the elements
if (filtered[element.callRoot]) filtered[element.callRoot].push(element); // if callRoot already exists in filtered object
else filtered[element.callRoot] = [element]; // else create property with callRoot as name -> here we push all the objects with the same callRoot name
})
return filtered;
};
const foo = function (data, element) {
const filtered = filterData(data);
// starting to create Table
// creating static table element, here becomes the element argument useful
const table = document.createElement('table');
element.appendChild(table);
// now we start creating the tbodies, trs and tds with the filtered data
// so we go through our filtered object by looping through an array of the keys ('@S','@C','@W')
Object.keys(filtered).forEach(property => {
// for each property we will create the tbody and tr + th and append them
const tbody = document.createElement('tbody');
table.appendChild(tbody);
let tr = document.createElement('tr');
tbody.appendChild(tr);
const th = document.createElement('th');
th.setAttribute('colspan', 9); // adding colspan attribute
th.textContent = filtered[property][0].userDescription; // taking the description as th text
tr.appendChild(th);
// now we create the rest of the tbody
// since i dont know where the data for the table comes from i will use the defined data from your example html output
// creating tr for our header tds
tr = document.createElement('tr');
tbody.appendChild(tr);
const definedDataArrayHeaders = ['Month', 'Last', 'Change', 'High', 'Low']; // headers from your example
definedDataArrayHeaders.forEach(element => { // going through the headers
const td = document.createElement('td');
td.textContent = element; // writing the header inside the td
tr.appendChild(td);
});
const definedDataArrayTds = ['August 2022', "1265'2", "-2'4", "1275'2", "1261'4"]; // tds from your example
for (let i of filtered[property]) { // will loop through each object inside our filtered array -> each tr in our future table
const tr = document.createElement('tr'); // creating tr for each data
tbody.appendChild(tr);
definedDataArrayTds.forEach(element => { // looping through the td data
const td = document.createElement('td');
td.textContent = element; // writing the data inside the td
tr.appendChild(td);
})
}
})
}
foo(commodities, document.querySelector('div')); // calling the function with data and Element where the table should be appended to
FALSE 旧使用数据:
const commodities = [
{
actualSymbol: "@SF22",
callRoot: "@S",
open: 1.00,
close: 2.00,
userDescription: "SOYBEANS",
// Other data
},
{
actualSymbol: "@SH22",
callRoot: "@S",
open: 4.00,
close: 6.00,
userDescription: "SOYBEANS",
// Other data
},
{
actualSymbol: "@SK22",
callRoot: "@S",
open: 0.50,
close: 2.30,
userDescription: "SOYBEANS",
// Other data
},
{
actualSymbol: "@CH22",
callRoot: "@C",
open: 0.25,
close: 0.75,
userDescription: "CORN",
// Other data
},
{
actualSymbol: "@CK22",
callRoot: "@C",
open: 5.00,
close: 6.75,
userDescription: "CORN",
// Other data
},
{
actualSymbol: "@CN22",
callRoot: "@C",
open: 1.00,
close: 2.00,
userDescription: "CORN",
// Other data
},
{
actualSymbol: "@WH22",
callRoot: "@W",
open: 3.25,
close: 2.00,
userDescription: "WHEAT",
// Other data
},
{
actualSymbol: "@WK22",
callRoot: "@W",
open: 1.00,
close: 2.00,
userDescription: "WHEAT",
// Other data
},
{
actualSymbol: "@WN22",
callRoot: "@W",
open: 0.10,
close: 0.20,
userDescription: "WHEAT",
// Other data
}
];
但是对于正确的示例输出,这是 html 输出:
<div>
<table>
<tbody>
<tr>
<th colspan="9">SOYBEANS</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">CORN</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">WHEAT</th>
</tr>
<tr>
<td>Month</td>
<td>Last</td>
<td>Change</td>
<td>High</td>
<td>Low</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
<tr>
<td>August 2022</td>
<td>1265'2</td>
<td>-2'4</td>
<td>1275'2</td>
<td>1261'4</td>
</tr>
</tbody>
</table>
</div>
新解决方案,希望这个能正常工作哈哈
这里是新版的脚本,肯定不好,就当是自己的攻略吧
const filterData2 = function (data) {
const filtered = {};
const wantedData = ['month', 'change', 'last', 'high', 'low', 'settlePrice'];
data.forEach(element => { // going through all the elements
// now using userDescript as key since its a bit more precise
if (filtered[element.userDescription]) { // if userDescription already exists in filtered object
const piece = [];
// now we extract only the data we need for our html table:
Object.entries(element).forEach(array => {
if (wantedData.includes(array[0])) array[1]?.number ? piece.push([array[0], array[1].number]) : piece.push([array[0], array[1]]);
});
filtered[element.userDescription].push(piece);
}
else {// else create property with userDescription as name -> here we push all the objects with the same callRoot name
const piece = [];
filtered[element.userDescription] = [];
Object.entries(element).forEach(array => {
if (wantedData.includes(array[0])) array[1]?.number ? piece.push([array[0], array[1].number]) : piece.push([array[0], array[1]]);
});
filtered[element.userDescription].push(piece);
}
})
return filtered;
};
// needed since i structured my filtered data different
const getValue = (arr, string) => arr.find(pair => pair[0] === string);
const foo2 = function (data, element) {
const filtered = filterData2(data);
// starting to create Table
// creating static table element, here becomes the element argument useful
const table = document.createElement('table');
element.appendChild(table);
// now we start creating the tbodies, trs and tds with the filtered data
// so we go through our filtered object by looping through an array of the keys in example:('SOYBEANS','CORN','WHEAT')
Object.keys(filtered).forEach(key => {
// key will be either 'SOYBEANS', 'CORN', 'WHEAT' - in this example in exactly this order
// for each key we will create the tbody and tr + th and append them
const tbody = document.createElement('tbody');
table.appendChild(tbody);
let tr = document.createElement('tr'); // using let here since we are going to overwrite this variable later so we dont have to create a new one
tbody.appendChild(tr);
const th = document.createElement('th');
th.setAttribute('colspan', 9); // adding colspan attribute
th.textContent = key; // taking the key as a header
tr.appendChild(th);
// now we create the rest of the tbody
// now since we filtered the data so in our filtered variable are only the necessary values for our table except the Settle Date
// creating tr for our header tds
tr = document.createElement('tr');
tbody.appendChild(tr);
const definedDataArrayHeaders = ['MONTH', 'LAST', 'CHANGE', 'HIGH', 'LOW', 'SETTLE DATE', 'SETTLE PRICE', 'MORE']; // Headers for the Table, can be anything - keep in Mind the date must be coming from somewhere for these headers, just some are covered by the filtered Array
definedDataArrayHeaders.forEach(header => { // going through the headers
const td = document.createElement('td');
td.textContent = header; // writing the header inside the td
tr.appendChild(td); // tr we created outside, so they all come into the same row
});
const definedDataArrayTds = ['month', "last", "change", "high", "low", "missing", "settlePrice", "missing"]; // this array must contain the names of the values inside the filtered array and must be in the same order as "definedDataArrayHeaders" so the data is in the right column
// since the Settle date and more value arent in the data/filtered array i will take placeholders so the table still renders right
// this part is needed to be changed a lot, since the data is now structured completely different
for (let i of filtered[key]) { // will loop through each object inside our filtered array -> each tr in our future table
const tr = document.createElement('tr'); // creating tr for each data
tbody.appendChild(tr);
definedDataArrayTds.forEach(element => { // looping through the td data
const td = document.createElement('td');
td.textContent = getValue(i, element)?.[1] || 'PLACEHOLDER'; // writing the data inside the td
tr.appendChild(td);
})
}
})
}
foo2(data, document.querySelector('div'));
此新示例中使用的数据:
const data = [
{
"symbol": {
"description": "SOYBEANS January 2022"
},
"actualSymbol": "@SF22",
"high": {
"number": 1396
},
"low": {
"number": 1374.75
},
"close": null,
"settlePrice": {
"number": 1401.5
},
"last": {
"number": 1378
},
"change": {
"number": -23.5
},
"month": "Jan 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "SOYBEANS March 2022"
},
"actualSymbol": "@SH22",
"high": {
"number": 1409.75
},
"low": {
"number": 1379
},
"close": null,
"settlePrice": {
"number": 1410.25
},
"last": {
"number": 1383.25
},
"change": {
"number": -27
},
"month": "Mar 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "SOYBEANS May 2022",
},
"actualSymbol": "@SK22",
"high": {
"number": 1418
},
"low": {
"number": 1387.5
},
"close": null,
"settlePrice": {
"number": 1418.75
},
"last": {
"number": 1391.25
},
"change": {
"number": -27.5
},
"month": "May 22",
"callRoot": "@S",
"userDescription": "SOYBEANS",
},
{
"symbol": {
"description": "CORN March 2022",
},
"actualSymbol": "@CH22",
"high": {
"number": 608
},
"low": {
"number": 596.75
},
"close": null,
"settlePrice": {
"number": 606.75
},
"last": {
"number": 599.25
},
"change": {
"number": -7.5
},
"month": "Mar 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "CORN May 2022",
},
"actualSymbol": "@CK22",
"high": {
"number": 608.5
},
"low": {
"number": 598.25
},
"close": null,
"settlePrice": {
"number": 607.75
},
"last": {
"number": 600.75
},
"change": {
"number": -7
},
"month": "May 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "CORN July 2022",
},
"actualSymbol": "@CN22",
"high": {
"number": 605.25
},
"low": {
"number": 595.5
},
"close": null,
"settlePrice": {
"number": 604.5
},
"last": {
"number": 598
},
"change": {
"number": -6.5
},
"month": "Jul 22",
"callRoot": "@C",
"userDescription": "CORN",
},
{
"symbol": {
"description": "WHEAT March 2022",
},
"actualSymbol": "@WH22",
"high": {
"number": 767.5
},
"low": {
"number": 748
},
"close": null,
"settlePrice": {
"number": 758.5
},
"last": {
"number": 763.75
},
"change": {
"number": 5.25
},
"month": "Mar 22",
"callRoot": "@W",
"userDescription": "WHEAT",
},
{
"symbol": {
"description": "WHEAT May 2022",
},
"actualSymbol": "@WK22",
"high": {
"number": 768.5
},
"low": {
"number": 750
},
"close": null,
"settlePrice": {
"number": 760.5
},
"last": {
"number": 765.5
},
"change": {
"number": 5
},
"month": "May 22",
"callRoot": "@W",
"userDescription": "WHEAT",
},
{
"symbol": {
"description": "WHEAT July 2022",
},
"actualSymbol": "@WN22",
"high": {
"number": 763.25
},
"low": {
"number": 747.25
},
"close": null,
"settlePrice": {
"number": 757
},
"last": {
"number": 760.5
},
"change": {
"number": 3.5
},
"month": "Jul 22",
"callRoot": "@W",
"userDescription": "WHEAT",
}
];
用上面的数据例子输出
<div>
<table>
<tbody>
<tr>
<th colspan="9">SOYBEANS</th>
</tr>
<tr>
<td>MONTH</td>
<td>LAST</td>
<td>CHANGE</td>
<td>HIGH</td>
<td>LOW</td>
<td>SETTLE DATE</td>
<td>SETTLE PRICE</td>
<td>MORE</td>
</tr>
<tr>
<td>Jan 22</td>
<td>1378</td>
<td>-23.5</td>
<td>1396</td>
<td>1374.75</td>
<td>PLACEHOLDER</td>
<td>1401.5</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>Mar 22</td>
<td>1383.25</td>
<td>-27</td>
<td>1409.75</td>
<td>1379</td>
<td>PLACEHOLDER</td>
<td>1410.25</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>May 22</td>
<td>1391.25</td>
<td>-27.5</td>
<td>1418</td>
<td>1387.5</td>
<td>PLACEHOLDER</td>
<td>1418.75</td>
<td>PLACEHOLDER</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">CORN</th>
</tr>
<tr>
<td>MONTH</td>
<td>LAST</td>
<td>CHANGE</td>
<td>HIGH</td>
<td>LOW</td>
<td>SETTLE DATE</td>
<td>SETTLE PRICE</td>
<td>MORE</td>
</tr>
<tr>
<td>Mar 22</td>
<td>599.25</td>
<td>-7.5</td>
<td>608</td>
<td>596.75</td>
<td>PLACEHOLDER</td>
<td>606.75</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>May 22</td>
<td>600.75</td>
<td>-7</td>
<td>608.5</td>
<td>598.25</td>
<td>PLACEHOLDER</td>
<td>607.75</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>Jul 22</td>
<td>598</td>
<td>-6.5</td>
<td>605.25</td>
<td>595.5</td>
<td>PLACEHOLDER</td>
<td>604.5</td>
<td>PLACEHOLDER</td>
</tr>
</tbody>
<tbody>
<tr>
<th colspan="9">WHEAT</th>
</tr>
<tr>
<td>MONTH</td>
<td>LAST</td>
<td>CHANGE</td>
<td>HIGH</td>
<td>LOW</td>
<td>SETTLE DATE</td>
<td>SETTLE PRICE</td>
<td>MORE</td>
</tr>
<tr>
<td>Mar 22</td>
<td>763.75</td>
<td>5.25</td>
<td>767.5</td>
<td>748</td>
<td>PLACEHOLDER</td>
<td>758.5</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>May 22</td>
<td>765.5</td>
<td>5</td>
<td>768.5</td>
<td>750</td>
<td>PLACEHOLDER</td>
<td>760.5</td>
<td>PLACEHOLDER</td>
</tr>
<tr>
<td>Jul 22</td>
<td>760.5</td>
<td>3.5</td>
<td>763.25</td>
<td>747.25</td>
<td>PLACEHOLDER</td>
<td>757</td>
<td>PLACEHOLDER</td>
</tr>
</tbody>
</table>
</div>