将二维数组渲染为分层 html 表

And*_*rle 1 javascript algorithm

我有这样的数据结构,顺序可以是随机的

const table = [
  ['A', 'a', 0],
  ['A', 'a', 1],
  ['A', 'b', 0],
  ['B', 'a', 0],
  ['B', 'b', 1],
  ['B', 'b', 0],
]
Run Code Online (Sandbox Code Playgroud)

这应该像这样在 html 中呈现为分层表

<table>
  <tr><td rowspan="3">A</td><td rowspan="2">a</td><td>0</td></tr>
  <tr><td>1</td></tr>
  <tr><td>b</td><td>0</td></tr>
  <tr><td rowspan="3">B</td><td>a</td><td>0</td></tr>
  <tr><td rowspan="2">b</td><td>0</td></tr>
  <tr><td>1</td></tr>
</table>
Run Code Online (Sandbox Code Playgroud)

我想知道什么是解决这个问题的有效方法。考虑过将列表转换为树,然后再转换回列表,但我不确定这是解决此问题的最佳方法。

Adr*_*and 5

将每个项目转换为具有 rowCount 的对象,并使用 0 表示前一个项目相同,因此不显示它。我不知道你正在使用什么视图绑定库,但在 Angular、Vue 或 React 中,绑定到表真的很容易。如果您使用纯 JavaScript 执行此操作,则必须在循环中创建 DOM 元素。

const table = [
  ['A', 'a', 0],
  ['A', 'a', 1],
  ['A', 'b', 0],
  ['B', 'a', 0],
  ['B', 'b', 1],
  ['B', 'b', 0],
];

const rowSpan = rows =>
  rows.map((row, rowIndex) =>
    row.map((item, colIndex) => ({ data: item, rowSpan: countRows(rows, rowIndex, colIndex) }))
  );

const countRows = (rows, rowIndex, colIndex) => {
  if (rowIndex > 0 && rows[rowIndex - 1][colIndex] === rows[rowIndex][colIndex]) {
    return 0;
  }
  let count = 1;
  while (count + rowIndex < rows.length && rows[rowIndex + count][colIndex] === rows[rowIndex][colIndex]) {
    count++;
  }
  return count;
};

const tableElement = document.createElement('table');

rowSpan(table).forEach(row => {
  const tr = document.createElement('tr');
  tableElement.appendChild(tr);
  row.forEach(item => {
    if (item.rowSpan) {
      const td = document.createElement('td');
      td.rowSpan = item.rowSpan;
      td.innerHTML = item.data.toString();
      tr.appendChild(td);
    }
  });
});

document.body.appendChild(tableElement);
Run Code Online (Sandbox Code Playgroud)
td {
  border: 1px solid black;
  vertical-align: top;
  padding: 3px 10px;
}
Run Code Online (Sandbox Code Playgroud)