Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在JavaScript中从带有缩进的平面列表构建树?_Javascript_Algorithm_Tree - Fatal编程技术网

如何在JavaScript中从带有缩进的平面列表构建树?

如何在JavaScript中从带有缩进的平面列表构建树?,javascript,algorithm,tree,Javascript,Algorithm,Tree,面对这个问题,我总是很挣扎,这需要一些认真的工作。我目前正在尝试解决这个问题,可能需要几天时间。想看看你是否有一个系统或简单的方法来解决这个问题 基本上,假设您有一个DOM节点的平面列表,以15px的步长填充左缩进。在视觉上,它形成了一个类似于文件浏览器的树。但在DOM的结构上,它是作为一个平面列表实现的。然后如何遍历列表并构建树 <div style='padding-left: 0px'>A</div> <div style='padding-left: 15p

面对这个问题,我总是很挣扎,这需要一些认真的工作。我目前正在尝试解决这个问题,可能需要几天时间。想看看你是否有一个系统或简单的方法来解决这个问题

基本上,假设您有一个DOM节点的平面列表,以15px的步长填充左缩进。在视觉上,它形成了一个类似于文件浏览器的树。但在DOM的结构上,它是作为一个平面列表实现的。然后如何遍历列表并构建树

<div style='padding-left: 0px'>A</div>
<div style='padding-left: 15px'>AA</div>
<div style='padding-left: 15px'>AB</div>
<div style='padding-left: 30px'>ABA</div>
<div style='padding-left: 30px'>ABB</div>
<div style='padding-left: 45px'>ABBA</div>
<div style='padding-left: 45px'>ABBB</div>
<div style='padding-left: 45px'>ABBC</div>
<div style='padding-left: 30px'>ABC</div>
<div style='padding-left: 15px'>AC</div>
<div style='padding-left: 0px'>B</div>
<div style='padding-left: 0px'>C</div>
...
你是怎么做到的?我迷路了:

let tree = []
let path = [0]

let items = list('div')

items.forEach(item => {
  let left = parseInt(item.style[`padding-left`] || 0) % 15
  let set = tree
  let p = path.concat()
  while (left) {
    let x = p.shift()
    set[x] = set[x] || { children: [] }
    set = set[x].children
    left--
  }
})

function list(s) {
  return Array.prototype.slice.call(document.querySelectorAll(s))
}

这是一个堆栈,因为它是连续的。像这样的

我们假设文件夹结构已完全“展开”,因此每个文件夹的父文件夹(最低文件夹除外,父文件夹是根文件夹)必须在当前文件夹之前进行检查。父级还必须具有较低的“左填充”赋值

ptrs
是一个堆栈,我们在其中附加对下一个检查文件夹的引用。堆栈顶部(末端)的文件夹是我们检查的最后一个文件夹。如果堆栈顶部的文件夹具有大于或等于“padding left”的赋值,则它们不可能是当前文件夹的父文件夹;在当前文件夹之后,我们不可能有更多的子文件夹,所以我们会删除(弹出)它们,直到找到最后一个“剩余填充”较低的文件夹

函数getData(s){
常量左=+s.match(/\d+/)[0];
常数title=s.match(/[A-Z]+/)[0];
返回[左,标题];
}
职能f(部门){
常数树={
标题:'根',
儿童:[]
};
常量ptrs=[[0,树]];//堆栈
for(让str of divs){
const[left,title]=getData(str);
while(ptrs.length&&ptrs[ptrs.length-1][0]>=左)
ptrs.pop();
父项=ptrs.length?ptrs[ptrs.length-1][1]:树;
const obj={title:title,子项:[]};
父.子.推(obj);
ptrs.推送([左,obj]);
}
回归树;
}
var divs=[
“A”,
“AA”,
“AB”,
“ABA”,
“ABB”,
“阿巴”,
“ABBB”,
“ABBC”,
“ABC”,
“AC”,
“B”,
“C”
]

控制台日志(f(divs))有趣的练习。这是另一种比以前的解决方案更详细的方法,但也适用于dom节点,而不是字符串html

constbuildtree=(选择器)=>{
常量元素=[…document.queryselectoral(选择器)]
.map((el,i)=>({el,title:el.textContent,idx:i,inset:parseInt(el.style.paddingLeft)});
const getChildren=({inset:pInset,idx:start})=>{
const nextParentIdx=elems.findIndex(({inset,idx},i)=>inset start);
常量描述=元素切片(开始,下一个Rentidx+1)
.filter(({inset})=>inset pInset==15);
返回描述图(getItem);
}
常量getItem=(o)=>{
返回{title:o.title,children:getChildren(o)}
}
返回elems.filter(({inset})=>!inset.map(getItem)
}
log(JSON.stringify(buildTree('div'),null,4))
。作为控制台包装{最大高度:100%!重要;顶部:0;}
A
AA
AB
阿巴
神甫
阿巴
缩写
ABBC
基础知识
自动控制
B

C
工作起来很有魅力!你能解释一下一般的技术吗?对我来说,它仍然像魔术一样:)也许可以在循环中遍历代码行以及它们背后的推理。@LancePollard当然。我补充了一个解释。如果还有什么需要澄清的,请告诉我。当然,我只使用字符串HTML作为示例。我当时正在打手机,而且我不想把它弄糟:)
let tree = []
let path = [0]

let items = list('div')

items.forEach(item => {
  let left = parseInt(item.style[`padding-left`] || 0) % 15
  let set = tree
  let p = path.concat()
  while (left) {
    let x = p.shift()
    set[x] = set[x] || { children: [] }
    set = set[x].children
    left--
  }
})

function list(s) {
  return Array.prototype.slice.call(document.querySelectorAll(s))
}