【问题标题】:creating a parent / child json object from a large array of path data in javascript从javascript中的大量路径数据创建父/子json对象
【发布时间】:2022-01-11 17:49:28
【问题描述】:

我有一个 Javascript 数组的形式:

var array = [Company_stock_content\\LightRhythmVisuals\\LRV_HD", "Big Media Test\\ArtificiallyAwake\\AA_HD", "Big Media Test\\Company\\TestCards_3840x2160\\TestCards_1920x1080",...]

我需要构造一个 JSON 形式的对象:

[
   {
        "data" : "parent",
        "children" : [
            {
                "data" : "child1",            
                "children" : [ ]
            }
        ]
    }
]

因此对于数组中的每个顶级节点,它可以有多个子节点,它们都有子节点。 例如,如果我们采用提供的数组剪辑器, 对应的 JSON 对象看起来是这样的

[{
    "data": "Company_stock_content",
    "children": [{
        "data": "LightRhythmVisuals",
        "children": [{
            "data": "LRV_HD"
        }]
    }]
}, {
    "data": "Big Media Test",
    "children": [{
        "data": "ArtificiallyAwake",
        "children": [{
            "data": "AA_HD"
        }]
    }, {
        "data": "Company",
        "children": [{
            "data": "TestCards_3840x2160"
        }]
    }]
}]

考虑到原始数组可以有数万个条目,我如何从给定的数据中构造这个结构?

【问题讨论】:

  • 数组与JSON的数据格式有什么关系?
  • 那么,您可以更新示例以显示您想要的实际输出吗?
  • 你可以走递归路线,但我建议你首先循环遍历主数组,拆分字符串,然后循环遍历它。
  • 感谢您的耐心和回复,您能详细解释一下您所说的拆分字符串是什么意思吗?进入一个新数组?
  • 目前尚不清楚具体问题是什么——这似乎是保留节点集合并递归处理字符串的问题(尽管我会在“根”节点启动节点并且输出使用根节点的子节点)。

标签: javascript arrays json


【解决方案1】:

这是一种将血统转换为层次结构的方法。一个简单的防止循环的方法是在设置父子关系时保留父指针并采取惰性方法(如果描述了冲突的关系,则最后一个获胜)。

考虑血统:

["A\\E", "A\\F", "B\\G\\I", "B\\G\\J", "C\\H"]

描述这棵树:

  A     B     C
  |     |     |
E   F   G     H 
        |
       I J

const array = ["A\\E", "A\\F", "B\\G\\I", "B\\G\\J", "C\\H"];
const lineages = array.map(string => string.split("\\"));

let nodes = {}

function createParentChild(parentName, childName) {
  const nodeNamed = name => {
    if (nodes[name]) return nodes[name];
    nodes[name] = { name, children: [], closed: false };
    return nodes[name];
  };
  let parent = nodeNamed(parentName)
  let child = nodeNamed(childName)
  if (child.parent) {
    // if this child already has a parent, we have an ill-formed input
    // fix by undoing the existing parent relation, remove the child from its current parent
    child.parent.children = child.parent.children.filter(c => c.name !== childName);
  }
  child.parent = parent
  if (!parent.children.includes(child))
    parent.children.push(child);
}

lineages.forEach(lineage => {
   for (i=0; i<lineage.length-1; i++) {
     createParentChild(lineage[i], lineage[i+1]);
   }
 })

 let roots = Object.values(nodes).filter(node => !node.parent)
 Object.values(nodes).forEach(node => delete node.parent)
 
 console.log(roots)

这种方法也适用于像这样的(可能是病态的)输入

// Here, "F" appears as a descendant of "A" and "B"
["A\\E", "A\\F", "B\\G\\I", "B\\G\\F", "C\\H"]

最后一个获胜:

  A     B     C
  |     |     |
  E     G     H 
        |
       I F

【讨论】:

  • 如果我想向 json 对象添加一个额外的参数,例如在 nodeNamed const 中有一个布尔值 closed = true 的状态,你将如何添加该功能?
  • @Carpathea,当然。就像我在编辑中所做的那样,在 nodeNamed 函数中添加其他道具,或者在返回父对象和子对象后这样做。
  • 非常感谢!
【解决方案2】:

类似这样的:

const array = ["Company_stock_content\\LightRhythmVisuals\\LRV_HD", "Big Media Test\\ArtificiallyAwake\\AA_HD", "Big Media Test\\Company\\TestCards_3840x2160\\TestCards_1920x1080"];

const result = array.reduce((acc, item) => {
  item.split('\\').forEach((entry, index, splits) => {
    acc[entry] = acc[entry] || { data: entry, children: [] };
    if (index > 0) {
      if (!acc[splits[index-1]].children.some(child => child.data === entry)) {
        acc[splits[index-1]].children.push(acc[entry]);
      }
    } else {
      if (!acc.children.some(root => root.data === entry)) {
        acc.children.push(acc[entry]);
      }
    }
  });
  return acc;
}, { children: []}).children;

console.log(result);

【讨论】:

  • 然后转成 JSON JSON.stringify(result)
  • 此方法的行为我只能在图片中解释i.imgur.com/yxbfveN.png 每个条目都应该像父子层次结构一样是唯一的,但每次节点可能存在时,它都会被放置在结果中
  • @Carpathea 进行小改动以删除子项中的重复项。已更新。
  • @ProGu - 我认为 OP 意味着在输入中描述血统,旨在将它们转换为层次结构。如果不同层次级别的节点匹配,这个答案将产生一个循环图。例如Given["A\\B\\C\\D", "E\\F\\B\\G"] , B 不是 AF 的孩子。 (至少我是这么看问题的)
  • @danh 在示例数组中,元素不是孤立的。 Big Media Test 是组合的,所以我假设 CG 都是 B 的孩子。你是对的,如果A 出现在某个地方作为B 的孩子,例如,它是循环的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-14
  • 2020-04-19
  • 1970-01-01
  • 2020-03-03
  • 1970-01-01
  • 2023-01-25
相关资源
最近更新 更多