本文旨在提供一种使用 JavaScript 解析包含嵌套括号的字符串的通用方法,通过构建 BracketTree 类,能够有效地处理不平衡的括号输入,并遍历树结构以查找特定模式的匹配项,无需复杂的正则表达式即可实现精准匹配。
BracketTree 类:解析嵌套括号的利器
正则表达式在处理嵌套结构时常常显得力不从心,容易出现匹配错误。BracketTree 类提供了一种更可靠的解决方案,它通过将字符串解析成树形结构,从而能够轻松地处理嵌套的括号,即使括号不平衡也能正确解析。
构造函数
BracketTree 类的构造函数接收两个参数:brackets(包含开始和结束括号的字符串)和 String(需要解析的字符串)。
class BracketTree { constructor (brackets, string) { if (typeof brackets != 'string' || brackets.length != 2 || brackets[0] == brackets[1]) { return null; } let opening = brackets[0]; let closing = brackets[1]; // ... 内部解析函数 ... } }
构造函数首先进行参数校验,确保 brackets 是一个包含两个不同字符的字符串。然后,它定义了内部的 parse 函数,用于递归地解析字符串并构建树形结构。
立即学习“Java免费学习笔记(深入)”;
内部解析函数 parse
parse 函数是 BracketTree 的核心,它接收一个起始位置 start 作为参数,并递归地解析字符串,构建一个表示括号结构的树形对象。
function parse (start) { let children = []; let pos = start; loop: while (pos < string.length) { switch (string[pos]) { case opening: let child = parse(pos + 1); children.push(child); if (child.end == string.length) { break loop; } pos = child.end; break; case closing: if (start == 0) { children = [{ children, start, end: pos, opened: false, closed: true, contents: string.slice(0, pos) }]; } else { return { children, start, end: pos, opened: true, closed: true, contents: string.slice(start, pos) }; } } pos++; } return (start == 0)? { children, start, end: string.length, opened: false, closed: false, contents: string }: { children, start, end: string.length, opened: true, closed: false, contents: string.slice(start) }; }
parse 函数遍历字符串,遇到开始括号时递归调用自身,创建一个子节点并添加到当前节点的 children 数组中。遇到结束括号时,返回一个包含子节点信息的对象。如果括号不平衡,parse 函数会尽力构建尽可能完整的树形结构。
traverse 方法:遍历树形结构
BracketTree 类还提供了一个 traverse 方法,用于遍历构建好的树形结构,并对每个节点执行回调函数。
traverse (callback) { if (typeof callback != 'function') { return false; } let root = this.root; let input = root.contents; let nodeId = 0; function recurse (parent, level) { // ... 内部递归函数 ... } recurse(root, 0); return true; }
traverse 方法接收一个回调函数 callback 作为参数,该函数将在每个节点上被调用。traverse 方法使用内部的 recurse 函数进行递归遍历。
使用示例
以下是一个使用 BracketTree 类的示例:
let input = 'NOT OPENED {3}2}1}***{avatarurl {id {message}}} blah blah blah {1{2{3} NOT CLOSED'; let tree = new BracketTree('{}', input); function filteredTraverse (caption, leafFilter, branchFilter) { console.log(`${'-'.repeat(29 - caption.length/2)} ${caption} `.padEnd(60, '-')); leafFilter ??= () => true; branchFilter ??= () => true; tree.traverse((args) => { if (args.branch) { return branchFilter(args); } if (leafFilter(args)) { console.log(`${' '.repeat(args.level)}<${args.contents}>`); } }); } filteredTraverse( 'Ignore unbalanced and all their descendants', null, ({branch}) => branch.opened && branch.closed ); filteredTraverse( 'Ignore unbalanced but include their descendants', ({parent}) => parent.opened == parent.closed ); filteredTraverse( 'Ignore empty', ({start, end}) => start != end ); filteredTraverse( 'Show non-empty first children only', ({childId, start, end}) => childId == 0 && start != end );
这段代码首先创建了一个 BracketTree 对象,然后定义了一个 filteredTraverse 函数,该函数使用 traverse 方法遍历树形结构,并根据提供的过滤器输出特定节点的信息。
总结
BracketTree 类提供了一种强大的方法来解析包含嵌套括号的字符串。与正则表达式相比,它更易于理解和维护,并且能够更好地处理不平衡的括号。通过使用 BracketTree 类,您可以轻松地提取和处理嵌套结构中的信息,从而简化您的 JavaScript 代码。在需要处理复杂嵌套结构的场景下,BracketTree 类是一个值得考虑的替代方案。
评论(已关闭)
评论已关闭