【问题标题】:Delimited text to nested javascript object/JSON分隔文本到嵌套的 javascript 对象/JSON
【发布时间】:2018-06-04 04:07:17
【问题描述】:

我有格式的文本

var text = "{{A-B-C}{A-C-B}D-B}{E}F" //example 1

文本可以是其他内容,例如:

var text = "{{{A-B-C}{C-A-B}D-E}{B-C}E-A}{F}G" //example 2

因此节点结构可以改变,但 - 和 {} 的分隔符保持不变以指示层次结构。

我想以此创建一棵树作为 javascript 对象或用于 d3js 树布局的 JSON。我可以使用 lodash/jquery 或我希望的任何其他库。

我需要的最终布局就像这张图片,对于上面的 var text 示例 1

如何将字符串转换为如下格式的嵌套数据(var text 示例 1)。我一直在努力寻找一种方法来做到这一点。任何帮助或指导表示赞赏。

var textobject = {
  name: "F",
  children: [{
      name: "E",
      children: []
    },
    {
      name: "B",
      children: [{
        name: "D",
        children: [{
          name: "B",
          children: [{
            name: "C",
            children: [{
              name: "A",
              children: []
            }, ]
          }, ]
        }, {
          name: "C",
          children: [{
            name: "B",
            children: [{
              name: "A",
              children: []
            }, ]
          }, ]
        }, ]
      }, ]
    },
  ]
}

【问题讨论】:

  • been struggling to find a way to do it in an efficient manner. 从您认为效率低下的事情开始,然后改进它 - 发布代码?
  • 在图像和文本输入中:A-B-C 处于同一级别,但在所需的输出中:AB 的子代C 的子代,有点困惑..
  • 感谢您查看@Taki。一切都是某物的孩子。那就是 - 表示左边的字符是右边的字符的孩子。 { } 括号表示具有分支的子级。这是否澄清了一点? - 请原谅我手机上的简洁性。

标签: javascript json string d3.js lodash


【解决方案1】:

您可以通过将数组用作堆栈来解决此问题。下面的代码的cmets有一个正确的解释。

function parseTree(string) {
  // split string into an array
  // reduce the array into a proper tree where the 
  // first and last item will be the entire tree, hence,
  // the access of the first index from the last part
  // of this expression
  return string.split(/(}|{|\-)/)
    .reduce(parseTreeReducer, [])[0];
}

function parseTreeReducer(array, ch, index, original) {
  // always track the index of the open bracket 
  // from the array stack
  let indexBracket = array.lastIndexOf('{');

  if(ch === '{') { // is it an open bracket?
    // store it in the array stack!
    array.push(ch); 
  } else if(ch === '}') { // is it a close bracket?
    // remove the last open bracket
    // this prepares the nodes after the open bracket index
    // to be the children of the next node
    array.splice(indexBracket, 1); 
  } else if(ch !== '-' && ch) { // make sure to ignore '-' key

    // push the node in the array stack
    array.push({ 
      name: ch, // name
      // ensure that we only get the nodes that are after the 
      // last open bracket from the array stack and remove them.
      // These removed nodes will be assigned as children for
      // this current node
      children: array.splice(
        // make sure we don't delete the open bracket
        indexBracket + 1, 
        // only remove items beyond the open bracket index
        array.length - indexBracket - 1 
      ).reverse() // reverse to represent the expected output (optional!)
    });

  }
  // return the array stack
  return array;
}

function parseTree(string) {
  // split string into an array
  // reduce the array into a proper tree where the 
  // first and last item will be the entire tree, hence,
  // the access of the first index from the last part
  // of this expression
  return string.split(/(}|{|\-)/)
    .reduce(parseTreeReducer, [])[0];
}

function parseTreeReducer(array, ch, index, original) {
  // always track the index of the open bracket 
  // from the array stack
  let indexBracket = array.lastIndexOf('{');

  if(ch === '{') { // is it an open bracket?
    // store it in the array stack!
    array.push(ch); 
  } else if(ch === '}') { // is it a close bracket?
    // remove the last open bracket
    // this prepares the nodes after the open bracket index
    // to be the children of the next node
    array.splice(indexBracket, 1); 
  } else if(ch !== '-' && ch) { // make sure to ignore '-' key
  
    // push the node in the array stack
    array.push({ 
      name: ch, // name
      // ensure that we only get the nodes that are after the 
      // last open bracket from the array stack and remove them.
      // These removed nodes will be assigned as children for
      // this current node
      children: array.splice(
        // make sure we don't delete the open bracket
        indexBracket + 1, 
        // only remove items beyond the open bracket index
        array.length - indexBracket - 1 
      ).reverse() // reverse to represent the expected output (optional!)
    });

  }
  // return the array stack
  return array;
}

/* THE CODE BELOW IS ONLY FOR DEMO USAGE */

var input = document.querySelector('input');
var output = document.querySelector('pre');

setOutput();
input.addEventListener('keyup', setOutput);

function setOutput() {
  output.innerHTML = JSON.stringify(parseTree(input.value), 0, 4);
}
.as-console-wrapper{min-height:100%;top:0}
input{width: 100%}
pre{background-color: #ccc; padding: 1em}
<input type="text" 
  autofocus 
  value="{{Axe-Barathrum-Clockwork}{Abaddon-Clinkz-Bane Elemental}Dragon Knight-Bristleback}{Ezalor}Furion" />

<br>

<pre></pre>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-17
    • 2017-02-14
    • 1970-01-01
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多