如何将字符串的缩进级别解析为 JSON 对象?
How do I parse the indentation level of a string into a JSON Object?
我希望能够将一个字符串解析为一个 JSON 对象,就像这样(文本可以是任何东西,我只是这样放置它们以便您可以看到结构) :
A
A-A
A-B
A-B-A
A-B-B
A-C
A-C-A
B
进入一个 json 对象,结构如下:
[
{
"root": "A",
"content": [
{ "root": "A-A", "content": [] },
{
"root": "A-B",
"content": [
{ "root": "A-B-A", "content": [] },
{ "root": "A-B-B", "content": [] }
]
},
{
"root": "A-C",
"content": [
{ "root": "A-C-A", "content": [] }
]
}
]
},
{ "root": "B", "content": [] }
]
到目前为止,我有以下内容,但我不确定这是否是最好的方法。也许递归方法会更好?
let body = [];
let indentStack = [0];
for (let line of input.split('\n')) { // input is the string I'd like to parse
if (line.trim() == '') continue; // skips over empty lines
let indent = line.match(/^ +/);
indent = indent ? indent[0].length : 0; // matches the first group of spaces with regex, gets the indent level of this line
if (indentStack[indentStack.length-1] != indent)
if (indentStack.includes(indent)) indentStack.length = indentStack.indexOf(indent)+1; // remove all indent levels after it as it's returned back to a higher level
else stack.push(indent);
console.log(`${(indent + '[' + indentStack.join() + ']').padEnd(10, ' ')}: ${line}`); // debugging
if (indentStack.length == 1) body.push({ root: line, content: [] });
else {
body[body.length-1].content.push({ root: line.substring(indent), content: [] })
}
}
console.log(body)
我会这样做:
const data =
`A
A-A
A-B
A-B-A
A-B-B
A-C
A-C-A
B`;
function doTree(data)
{
let
res = []
, levels = [ res ]
;
for (let line of data.split('\n'))
{
let
level = line.search(/\S/) >> 1 // (index of first non whitespace char) / 2 --> IF indentation is 2 spaces
, root = line.trim()
, content = []
;
if (!root) continue
levels[level].push({root,content})
levels[++level] = content
}
return res
}
console.log( doTree(data) )
.as-console-wrapper {max-height: 100%!important;top:0 }
The question about indentations ...
这里你可以有不相等的缩进步骤,
带空格或带制表符。
(不要混用空格和制表符)
const data_023c = // indentation values are 0c, 2c, 3c
`A
A-A
A-B
A-B-A
A-B-B
A-C
A-C-A
B`;
const indentation= (()=> // IIFE
{
let
indents = []
, max = -1
;
return {
clear:() =>
{
indents.length = 0
max = -1
}
, get:(line, lNum='?' ) =>
{
let ncBefore = line.search(/\S/)
let level = indents.indexOf(ncBefore)
if (level===-1)
{
if (ncBefore < max) throw `error on indentation,\n line = ${lNum},\n line value is = "${line}"`
level = indents.push( ncBefore) -1
max = ncBefore
}
return level
}
}
})()
const doTree = data =>
{
let
res = []
, levels = [ res ]
, lineN = 0
;
indentation.clear()
for (let line of data.split('\n'))
{
lineN++ // line counter for indent error message
let
root = line.trim()
, content = []
;
if (!root) continue
let level = indentation.get(line, lineN)
levels[level].push({root,content})
levels[++level] = content
}
return res
}
console.log( doTree(data_023c) )
.as-console-wrapper {max-height: 100%!important;top:0 }
我希望能够将一个字符串解析为一个 JSON 对象,就像这样(文本可以是任何东西,我只是这样放置它们以便您可以看到结构) :
A
A-A
A-B
A-B-A
A-B-B
A-C
A-C-A
B
进入一个 json 对象,结构如下:
[
{
"root": "A",
"content": [
{ "root": "A-A", "content": [] },
{
"root": "A-B",
"content": [
{ "root": "A-B-A", "content": [] },
{ "root": "A-B-B", "content": [] }
]
},
{
"root": "A-C",
"content": [
{ "root": "A-C-A", "content": [] }
]
}
]
},
{ "root": "B", "content": [] }
]
到目前为止,我有以下内容,但我不确定这是否是最好的方法。也许递归方法会更好?
let body = [];
let indentStack = [0];
for (let line of input.split('\n')) { // input is the string I'd like to parse
if (line.trim() == '') continue; // skips over empty lines
let indent = line.match(/^ +/);
indent = indent ? indent[0].length : 0; // matches the first group of spaces with regex, gets the indent level of this line
if (indentStack[indentStack.length-1] != indent)
if (indentStack.includes(indent)) indentStack.length = indentStack.indexOf(indent)+1; // remove all indent levels after it as it's returned back to a higher level
else stack.push(indent);
console.log(`${(indent + '[' + indentStack.join() + ']').padEnd(10, ' ')}: ${line}`); // debugging
if (indentStack.length == 1) body.push({ root: line, content: [] });
else {
body[body.length-1].content.push({ root: line.substring(indent), content: [] })
}
}
console.log(body)
我会这样做:
const data =
`A
A-A
A-B
A-B-A
A-B-B
A-C
A-C-A
B`;
function doTree(data)
{
let
res = []
, levels = [ res ]
;
for (let line of data.split('\n'))
{
let
level = line.search(/\S/) >> 1 // (index of first non whitespace char) / 2 --> IF indentation is 2 spaces
, root = line.trim()
, content = []
;
if (!root) continue
levels[level].push({root,content})
levels[++level] = content
}
return res
}
console.log( doTree(data) )
.as-console-wrapper {max-height: 100%!important;top:0 }
The question about indentations ...
这里你可以有不相等的缩进步骤,
带空格或带制表符。
(不要混用空格和制表符)
const data_023c = // indentation values are 0c, 2c, 3c
`A
A-A
A-B
A-B-A
A-B-B
A-C
A-C-A
B`;
const indentation= (()=> // IIFE
{
let
indents = []
, max = -1
;
return {
clear:() =>
{
indents.length = 0
max = -1
}
, get:(line, lNum='?' ) =>
{
let ncBefore = line.search(/\S/)
let level = indents.indexOf(ncBefore)
if (level===-1)
{
if (ncBefore < max) throw `error on indentation,\n line = ${lNum},\n line value is = "${line}"`
level = indents.push( ncBefore) -1
max = ncBefore
}
return level
}
}
})()
const doTree = data =>
{
let
res = []
, levels = [ res ]
, lineN = 0
;
indentation.clear()
for (let line of data.split('\n'))
{
lineN++ // line counter for indent error message
let
root = line.trim()
, content = []
;
if (!root) continue
let level = indentation.get(line, lineN)
levels[level].push({root,content})
levels[++level] = content
}
return res
}
console.log( doTree(data_023c) )
.as-console-wrapper {max-height: 100%!important;top:0 }