Javascript 将数组添加到多维数组或对象中

Javascript 将数组添加到多维数组或对象中,javascript,Javascript,我正在将wysiwyg生成的内容解析到React中的目录小部件中 到目前为止,我正在遍历这些头并将它们添加到一个数组中 如何将它们全部放入一个多维数组或对象中(最好的方法是什么),使其看起来更像: h1-1 h2-1 h3-1 h1-2 h2-2 h3-2 h1-3 h2-3 h3-3 然后我可以在UI中用有序列表呈现它 const str=“h1-1h2-1h3-1somethingh1-2h2-2h3-2”; 常

我正在将
wysiwyg
生成的内容解析到React中的目录小部件中

到目前为止,我正在遍历这些头并将它们添加到一个数组中

如何将它们全部放入一个多维数组或对象中(最好的方法是什么),使其看起来更像:

h1-1
    h2-1
        h3-1

h1-2
    h2-2
        h3-2

h1-3
    h2-3
        h3-3
然后我可以在UI中用有序列表呈现它

const str=“h1-1h2-1h3-1something

h1-2h2-2h3-2”; 常量模式h1=/(.*)/g; 常数模式h2=/(.*)/g; 常量模式h3=/(.*)/g; 设h1s=[]; 设h2s=[]; 设h3s=[]; 让match1,match2,match3; while(matchh1=patternh1.exec(str)) h1s.推送(匹配H1[1]) while(matchh2=patternh2.exec(str)) h2s.推压(匹配H2[1]) while(match3=patternh3.exec(str)) h3s.push(匹配h3[1]) 控制台日志(h1s) 控制台日志(h2s)
console.log(h3s)
您可以简单地收集所有
h*
,然后对它们进行迭代以构建一个树:

使用ES6(我从您使用的
const
let
推断这是可以的)

const str=`
h1-1
h2-1
h3-1
某物

h1-2 h2-2 h3-2 ` 常数模式h=/(.*)/g; 设hs=[]; 让我们配对; while(match=patternh.exec(str)) 推送({lev:match[1],text:match[2]}) 控制台日志(hs) //使用以下格式构造树:[{value:…,子项:[{value:…,子项:[…]},…]},] const add=(res、lev、what)=>{ 如果(lev==0){ res.push({value:what,children:[]}); }否则{ 添加(res[res.length-1]。children,lev-1,what); } } //从空列表开始,使用上述方法将找到的所有hs减少到树中 常量树=hs.reduce((res,{lev,text})=>{ 添加(res,lev-1,文本); 返回res; }, []); 控制台日志(树);
但是,由于html标题本身不是树状结构(我猜这是您的用例),因此这仅在某些假设下有效,例如,除非上面有一个
,上面有一个
,否则您不能有
。它还将假定较低级别的标头始终属于紧接较高级别的最新标头

如果要进一步使用树结构,例如呈现TOC的代表性有序列表,可以执行以下操作:

// function to render a bunch of <li>s
const renderLIs = children => children.map(child => `<li>${renderOL(child)}</li>`).join('');

// function to render an <ol> from a tree node
const renderOL = tree => tree.children.length > 0 ? `<ol>${tree.value}${renderLIs(tree.children)}</ol>` : tree.value;

// use a root node for the TOC
const toc = renderOL({ value: 'TOC', children: tree });

console.log(toc);
//用于呈现一组
  • 的函数 const renderLIs=children=>children.map(child=>`
  • ${renderOL(child)}
  • `).join(“”); //函数从树节点渲染 const renderOL=tree=>tree.children.length>0`${tree.value}${renderLIs(tree.children)}`:tree.value; //使用TOC的根节点 const-toc=renderOL({value:'toc',children:tree}); 控制台日志(toc);

    希望有帮助。

    我不知道你的情况,但我讨厌用正则表达式解析HTML。相反,我认为让DOM处理这个问题是一个更好的主意:

    const str=`h1-1
    h3-1
    h3-2
    某物

    h1-2 h2-2 h3-2`; const wrapper=document.createElement('div'); wrapper.innerHTML=str.trim(); 设tree=[]; 设leaf=null; for(wrapper.querySelectorAll(“h1,h2,h3,h4,h5,h6”)的常量节点){ const nodeLevel=parseInt(节点标记名[1]); 常数newLeaf={ 级别:nodeLevel, text:node.textContent, 儿童:[], 父:叶 };
    while(leaf&&newLeaf.level您要做的是(文档大纲的变体),例如,从文档标题创建嵌套列表,尊重其层次结构

    使用DOM和DOMParser API的浏览器的一个简单实现如下所示(放入HTML页面并在ES5中编码以便于测试):

    
    文件大纲
    //包装在文档(和主体)元素中的测试字符串
    var str=“h1-1h2-1h3-1something

    h1-2h2-2h3-2”; //用于遍历DOM并发出SAX startElement事件的util 函数emitSAXLikeEvents(节点、处理程序){ handler.startElement(节点) 对于(var i=0;i
    我首先将您的片段解析为
    文档
    ,然后遍历它以创建类似SAX的
    startElement()
    调用。在
    startElement()
    函数中,根据最近创建的列表项(如果有)的排名检查标题元素的排名。然后在正确的层次结构级别追加一个新的列表项,并可能创建一个
    ol
    元素作为它的容器。请注意,现有的算法不适用于从层次结构中的
    h1
    跳到
    h3
    ,但可以轻松调整

    如果您想在node.js上创建一个大纲/内容表,可以让代码运行服务器端,但需要一个像样的HTML解析库(可以说是node.js的DOMParser polyfill)。还有用于创建大纲的和包,尽管我还没有测试过。这些包据说还可以处理诸如标题之类的特殊情况
    // function to render a bunch of <li>s
    const renderLIs = children => children.map(child => `<li>${renderOL(child)}</li>`).join('');
    
    // function to render an <ol> from a tree node
    const renderOL = tree => tree.children.length > 0 ? `<ol>${tree.value}${renderLIs(tree.children)}</ol>` : tree.value;
    
    // use a root node for the TOC
    const toc = renderOL({ value: 'TOC', children: tree });
    
    console.log(toc);
    
    <!DOCTYPE html>
    <html>
    <head>
    <title>Document outline</title>
    </head>
    <body>
    <div id="outline"></div>
    <script>
    
    // test string wrapped in a document (and body) element
    var str = "<html><body><h1>h1-1</h1><h2>h2-1</h2><h3>h3-1</h3><p>something</p><h1>h1-2</h1><h2>h2-2</h2><h3>h3-2</h3></body></html>";
    
    // util for traversing a DOM and emit SAX startElement events
    function emitSAXLikeEvents(node, handler) {
        handler.startElement(node)
        for (var i = 0; i < node.children.length; i++)
            emitSAXLikeEvents(node.children.item(i), handler)
        handler.endElement(node)
    }
    
    var outline = document.getElementById('outline')
    var rank = 0
    var context = outline
    emitSAXLikeEvents(
        (new DOMParser()).parseFromString(str, "text/html").body,
        {
            startElement: function(node) {
                if (/h[1-6]/.test(node.localName)) {
                    var newRank = +node.localName.substr(1, 1)
    
                    // set context li node to append
                    while (newRank <= rank--)
                        context = context.parentNode.parentNode
    
                    rank = newRank
    
                    // create (if 1st li) or
                    // get (if 2nd or subsequent li) ol element
                    var ol
                    if (context.children.length > 0)
                        ol = context.children[0]
                    else {
                        ol = document.createElement('ol')
                        context.appendChild(ol)
                    }
    
                    // create and append li with text from
                    // heading element
                    var li = document.createElement('li')
                    li.appendChild(
                      document.createTextNode(node.innerText))
                    ol.appendChild(li)
    
                    context = li
                }
            },
            endElement: function(node) {}
        })
    </script>
    </body>
    </html>