519 words
3 minutes
表格根据系统发育树叶节点顺序排序的完整实现方法

表格根据系统发育树叶节点顺序排序的完整实现方法#

1. 需求分析#

  • 目标:让表格的每一行顺序严格与系统发育树(Phylogenetic Tree)的叶节点顺序一致,实现树与表格的联动和一一对应。
  • 数据来源:树结构为 Newick 格式,表格数据为 txt/tsv 文件,二者通过叶节点名(如 Assembly 字段)关联。

2. 实现方案#

2.1 解析表格数据#

  • 读取 table.txt,按行分割,首行为表头,生成对象数组。
function parseTableTxt(txt) {
  const lines = txt.trim().split('\n')
  const header = lines[0].split('\t')
  return lines.slice(1).map(line => {
    const cols = line.split('\t')
    const obj = {}
    header.forEach((h, i) => {
      obj[h] = cols[i]
    })
    return obj
  })
}

2.2 获取树的叶节点顺序#

  • 渲染树后,递归遍历树结构,提取所有叶节点的 name,得到顺序数组。
function getLeafNamesFromNodes(nodeOrArray) {
  if (Array.isArray(nodeOrArray)) {
    return nodeOrArray.flatMap(getLeafNamesFromNodes)
  }
  if (!nodeOrArray.children || nodeOrArray.children.length === 0) {
    return [nodeOrArray.data.name]
  }
  return nodeOrArray.children.flatMap(getLeafNamesFromNodes)
}

2.3 排序表格数据#

  • 用叶节点顺序数组 leafOrderList 和表格数据 tableData,生成排序后的表格。
function sortTableByLeafOrder(leafOrder, tableRows) {
  const tableMap = new Map(tableRows.map(row => [row.Assembly, row]))
  return leafOrder.map(name => tableMap.get(name)).filter(Boolean)
}

2.4 表格渲染#

  • 在模板中用 sortedTableData 渲染表格:
<tr v-for="(row, idx) in sortedTableData" :key="row.Assembly">
  <td>{{ row.Assembly }}</td>
  <!-- 其他列 -->
</tr>

3. 技术要点#

特性说明
排序本质用树的叶节点顺序作为主序列,表格数据用 Map 快速索引,O(n) 完成排序
健壮性如树中有表格未匹配项,filter(Boolean) 可自动跳过,避免报错
响应式只要树或表格数据变化,排序自动更新,无需手动刷新
适用范围适用于任何 Newick 树和一一对应的表格数据

4. 完整示例#

// 1. 解析表格
tableData.value = parseTableTxt(tableTxt)

// 2. 渲染树后获取叶节点顺序
leafOrderList.value = getLeafNamesFromNodes(treeInstance.nodes)

// 3. 排序
const sortedTableData = computed(() => {
  if (!leafOrderList.value.length) return tableData.value
  return sortTableByLeafOrder(leafOrderList.value, tableData.value)
})

5. 总结#

  • 核心思想:树的叶节点顺序驱动表格排序,保证联动和一一对应。
  • 实现简洁高效,易于维护和扩展。
  • 适合所有需要”树-表联动排序”的前端可视化场景。
表格根据系统发育树叶节点顺序排序的完整实现方法
https://echooler.com/posts/2025-05-12-phylogenetic-tree-table-sorting/
Author
Echooler
Published at
2025-05-12
License
CC BY-NC-SA 4.0