You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS新手求助:将邻接矩阵转换为类JSON嵌套父子结构

邻接矩阵转指定父子对象结构问题

需求

我是JavaScript新手,需要把带区域信息的二维邻接矩阵数组转换成指定的类JSON父子对象结构,因为只有父子层级(无祖父节点),不需要递归实现。

原始数据

原始邻接矩阵(仅关注链接存在性,忽略权重):

const exampleRawLinks = [
  { n1: NaN, n2: 1.2, n3: NaN, n4: 1.3 },
  { n1: NaN, n2: NaN, n3: NaN, n4: 1.4 },
  { n1: NaN, n2: 1.5, n3: NaN, n4: 1.4 },
  { n1: NaN, n2: NaN, n3: 1.3, n4: NaN },
];

补充区域和节点名称后的数据:

const nodeLinks = [
  { region: 1, node: "n1", n1: NaN, n2: 1.2, n3: NaN, n4: 1.3 },
  { region: 1, node: "n2", n1: NaN, n2: NaN, n3: NaN, n4: 1.4 },
  { region: 2, node: "n3", n1: NaN, n2: 1.5, n3: NaN, n4: 1.4 },
  { region: 3, node: "n4", n1: NaN, n2: NaN, n3: 1.3, n4: NaN },
];

期望结果

转换后的结构(id和group对应区域,targets为当前节点有链接的节点名):

const dataFinal = {
  children: [
    {
      id: 1,
      children: [
        { id: "n1", group: 1, targets: ["n2", "n4"] },
        { id: "n2", group: 1, targets: ["n4"] }
      ]
    },
    {
      id: 2,
      children: [
        { id: "n3", group: 2, targets: ["n2", "n4"] }
      ]
    },
    {
      id: 3,
      children: [
        { id: "n4", group: 3, targets: ["n3"] }
      ]
    }
  ]
};

(注:原期望结果存在几处笔误,已修正,确保与原始数据对应)

尝试过程及问题

我试过用d3.groups()按区域分组,也写了一段代码,但targets数组始终为空,怀疑是slice的范围错误,当前代码:

dataFinal = Object.entries(nodeLinks)
  .map(d => ({
    id: d[1].region,
    children: [({
      id: d[1].node,
      group: d[1].region,
      targets: Object.keys(Array(d[1]).slice(2,-1).map(obj => _.omitBy(obj, _.isNull)))
    })]
  }));

解决方案

步骤1:按区域分组

用Array.reduce()先把nodeLinks按region分组,得到以区域为键、节点数组为值的对象:

const groupedByRegion = nodeLinks.reduce((acc, item) => {
  if (!acc[item.region]) {
    acc[item.region] = [];
  }
  acc[item.region].push(item);
  return acc;
}, {});

步骤2:转换每个节点并生成targets

对每个分组里的节点,过滤出除region和node外的属性,判断值是否为有效数值(不是NaN),收集这些属性名作为targets:

const dataFinal = {
  children: Object.entries(groupedByRegion).map(([regionId, nodes]) => ({
    id: Number(regionId),
    children: nodes.map(node => {
      // 生成targets:筛选出值不是NaN的节点名
      const targets = Object.keys(node)
        .filter(key => !['region', 'node'].includes(key))
        .filter(key => !Number.isNaN(node[key]));
      
      return {
        id: node.node,
        group: node.region,
        targets: targets
      };
    })
  }))
};

完整代码

const nodeLinks = [
  { region: 1, node: "n1", n1: NaN, n2: 1.2, n3: NaN, n4: 1.3 },
  { region: 1, node: "n2", n1: NaN, n2: NaN, n3: NaN, n4: 1.4 },
  { region: 2, node: "n3", n1: NaN, n2: 1.5, n3: NaN, n4: 1.4 },
  { region: 3, node: "n4", n1: NaN, n2: NaN, n3: 1.3, n4: NaN },
];

// 按区域分组
const groupedByRegion = nodeLinks.reduce((acc, item) => {
  if (!acc[item.region]) {
    acc[item.region] = [];
  }
  acc[item.region].push(item);
  return acc;
}, {});

// 转换为目标结构
const dataFinal = {
  children: Object.entries(groupedByRegion).map(([regionId, nodes]) => ({
    id: Number(regionId),
    children: nodes.map(node => {
      const targets = Object.keys(node)
        .filter(key => !['region', 'node'].includes(key))
        .filter(key => !Number.isNaN(node[key]));
      
      return {
        id: node.node,
        group: node.region,
        targets: targets
      };
    })
  }))
};

console.log(dataFinal);

代码说明

  • 用reduce分组更直观,无需额外依赖(如果已使用d3,也可以用d3.groups(nodeLinks, d => d.region)后转换结构)
  • 生成targets时直接过滤无关字段并判断数值有效性,避免了原代码中Array(d[1])这类错误操作导致的slice失效问题
  • 修正了原期望结果的笔误,确保输出与原始数据完全对应

内容的提问来源于stack exchange,提问作者Skyehawk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 04:30:51