查找字符串行是嵌套的还是另一行的子行
Find if a string line is nested or is a child of another line
我想为某种文件编写一个小型解析器,我必须完成的其中一件事是查找一行是否在另一行中,用缩进(空格或制表符)定义它。
示例:
This is the main line
This is a nested or child line
我试图通过读取行中的第一个字符位置并将其与前一个字符进行比较来确定这一点,如下所示:
var str = ' hello';
str.indexOf(str.match(/\S|$/).shift());
我确定这不是最好的方法,而且看起来很糟糕,我还有其他问题需要解决,例如检查缩进是否由空格(2 或 4)、制表符或 passing/maintaining 上一行(对象)的状态。
此外,行可以无限嵌套,当然我正在寻找一个好的和高性能的算法(或想法)或模式,而不是我认为相对容易做但容易出错的简单检查。我相信使用解析器和编译器的人已经解决了这个问题。
编辑:
str.search(/\S/);
@Oriol 提案看起来好多了
这通常是您编写解析器的目的,而不是纯粹依赖正则表达式。如果嵌套决定了深度,那么您有两件事要解决:1) 找到任意线条的深度,以及 2) 遍历线条集并跟踪每一行,哪一行的前一行具有较低的深度值。
如果您熟悉 Javascript 中的 RegExp 函数,那么第一个是微不足道的:
function getDepth(line) {
// find leading white space
var ws = str.match(/^(\s+)/);
// no leading white space?
if (ws === null) return 0;
// leading white space -> count the white space symbols.
// obviously this goes wrong for mixed spaces and tabs, and that's on you.
return ws[0].split('').length;
}
第二部分比较简单,因此您有多种选择。您可以遍历所有行,并跟踪行号列表,在深入时推入列表并在返回时从列表中弹出,或者您可以构建一个简单的树结构(这通常要好得多,因为它使您可以更轻松地扩展其功能)使用标准的树构建方法。
function buildTree(lines, depths) {
if (!depths) {
var depths = lines.map(e => getDepth);
return buildTree(lines, depths);
}
var root = new Node();
for(var pos=0, end=lines.length; pos<end; pos++) {
var line = lines[pos];
var depth = depths[pos];
root.insert(line, depth);
}
}
当然是用一个简单的Node
对象
var Node = function(text, depth) {
this.children = [];
this.line = text.replace(/^\s+/,'');
this.depth = depth;
}
Node.prototype = {
insert: function(text, depth) {
// this is where you become responsible: we need to insert
// a new node inside of this one if the depths indicate that
// is what should happen, but you're on the hook for determining
// what you want to have happen if the indentation was weird, like
// a line at depth 12 after a line at depth 2, or vice versa.
}
}
我想为某种文件编写一个小型解析器,我必须完成的其中一件事是查找一行是否在另一行中,用缩进(空格或制表符)定义它。
示例:
This is the main line
This is a nested or child line
我试图通过读取行中的第一个字符位置并将其与前一个字符进行比较来确定这一点,如下所示:
var str = ' hello';
str.indexOf(str.match(/\S|$/).shift());
我确定这不是最好的方法,而且看起来很糟糕,我还有其他问题需要解决,例如检查缩进是否由空格(2 或 4)、制表符或 passing/maintaining 上一行(对象)的状态。
此外,行可以无限嵌套,当然我正在寻找一个好的和高性能的算法(或想法)或模式,而不是我认为相对容易做但容易出错的简单检查。我相信使用解析器和编译器的人已经解决了这个问题。
编辑:
str.search(/\S/);
@Oriol 提案看起来好多了
这通常是您编写解析器的目的,而不是纯粹依赖正则表达式。如果嵌套决定了深度,那么您有两件事要解决:1) 找到任意线条的深度,以及 2) 遍历线条集并跟踪每一行,哪一行的前一行具有较低的深度值。
如果您熟悉 Javascript 中的 RegExp 函数,那么第一个是微不足道的:
function getDepth(line) {
// find leading white space
var ws = str.match(/^(\s+)/);
// no leading white space?
if (ws === null) return 0;
// leading white space -> count the white space symbols.
// obviously this goes wrong for mixed spaces and tabs, and that's on you.
return ws[0].split('').length;
}
第二部分比较简单,因此您有多种选择。您可以遍历所有行,并跟踪行号列表,在深入时推入列表并在返回时从列表中弹出,或者您可以构建一个简单的树结构(这通常要好得多,因为它使您可以更轻松地扩展其功能)使用标准的树构建方法。
function buildTree(lines, depths) {
if (!depths) {
var depths = lines.map(e => getDepth);
return buildTree(lines, depths);
}
var root = new Node();
for(var pos=0, end=lines.length; pos<end; pos++) {
var line = lines[pos];
var depth = depths[pos];
root.insert(line, depth);
}
}
当然是用一个简单的Node
对象
var Node = function(text, depth) {
this.children = [];
this.line = text.replace(/^\s+/,'');
this.depth = depth;
}
Node.prototype = {
insert: function(text, depth) {
// this is where you become responsible: we need to insert
// a new node inside of this one if the depths indicate that
// is what should happen, but you're on the hook for determining
// what you want to have happen if the indentation was weird, like
// a line at depth 12 after a line at depth 2, or vice versa.
}
}