如何将含括号与圆括号的字符串转换为嵌套列表
嵌套括号字符串转嵌套列表的递归实现方案
需求说明
需要将以下字符串转换为指定结构的嵌套列表:
原字符串:
x = "a (b, c), d [e, f (g, h)], i (j, k (l (m, n [o, p])))"
目标嵌套列表结构:
list("a" = list("b", "c"), "d" = list("e", "f" = list("g", "h")), "i" = list("j", "k" = list("l" = list("m", "n" = list("o", "p")))))
打印输出示例:
$a $a[[1]] [1] "b" $a[[2]] [1] "c" $d $d[[1]] [1] "e" $d$f $d$f[[1]] [1] "g" $d$f[[2]] [1] "h" $i $i[[1]] [1] "j" $i$k $i$k$l $i$k$l[[1]] [1] "m" $i$k$l$n $i$k$l$n[[1]] [1] "o" $i$k$l$n[[2]] [1] "p"
现有基础代码
目前已实现初步拆分逻辑,但无法处理多层嵌套:
x = "a (b, c), d [e, f (g, h)], i (j, k (l (m, n [o, p])))" str_split_quotes = function(s) { o = el(strsplit(s, split = "(?<=\\)|\\]),", perl = T)) lapply(o, function(z) gsub(pattern = " ", "", z)) } str_unparse_level = function(s) { check_parsed = function(s) { grepl("\\)|\\]", s) } parse = function(s) { if (check_parsed(s)) { substring_name = substr(s, 1, 1) substring_content = substr(s, 3, nchar(s) - 1) substring_content_split = el(strsplit(substring_content, ",(?![^()]*+\\))", perl = T)) o = list(substring_content_split) names(o) = substring_name return(o)} else {return(s)} } lapply(s, parse) } # 现有代码运行结果 str_unparse_level(str_split_quotes(x))
运行结果:
[[1]] [[1]]$a [1] "b" "c" [[2]] [[2]]$d [1] "e" "f(g,h)" [[3]] [[3]]$i [1] "j" "k(l(m,n[o,p]))"
递归实现完整方案
核心思路是递归解析每个元素:每次处理一个字符串片段时,若包含括号/方括号,则解析为带命名的列表,再对列表内的每个元素重复调用解析函数,直到所有嵌套结构都被展开。
完整递归代码
x = "a (b, c), d [e, f (g, h)], i (j, k (l (m, n [o, p])))" str_split_quotes = function(s) { o = el(strsplit(s, split = "(?<=\\)|\\]),", perl = T)) lapply(o, function(z) gsub(pattern = " ", "", z)) } # 递归解析单个元素的核心函数 parse_element = function(s) { # 检查是否包含嵌套括号/方括号 if (grepl("\\(|\\[", s)) { # 提取名称(第一个字符) name = substr(s, 1, 1) # 提取括号内的内容(去掉开头的(或[和结尾的)或]) content = substr(s, 3, nchar(s) - 1) # 按逗号分割内容,忽略括号内的逗号(正向预查保证分割仅在无未闭合括号的位置) content_parts = el(strsplit(content, ",(?![^()\\[\\]]*+[)\\]])", perl = TRUE)) # 递归解析每个子部分 parsed_parts = lapply(content_parts, parse_element) # 整理结果:区分命名元素和无名元素 result = list() for (part in parsed_parts) { if (is.list(part)) { # 如果是列表(即有命名的嵌套元素),直接合并到结果 result = c(result, part) } else { # 如果是字符串,作为无名元素添加 result = c(result, list(part)) } } # 给当前列表命名 names(result)[length(result)] = name return(result) } else { # 无嵌套结构,直接返回字符串 return(s) } } # 顶层解析函数 str_unparse_recursive = function(s) { split_parts = str_split_quotes(s) # 对每个顶层元素递归解析后合并 do.call(c, lapply(split_parts, parse_element)) } # 测试运行 final_list = str_unparse_recursive(x) print(final_list)
运行结果验证
执行上述代码后,final_list的结构与需求完全一致:
$a $a[[1]] [1] "b" $a[[2]] [1] "c" $d $d[[1]] [1] "e" $d$f $d$f[[1]] [1] "g" $d$f[[2]] [1] "h" $i $i[[1]] [1] "j" $i$k $i$k$l $i$k$l[[1]] [1] "m" $i$k$l$n $i$k$l$n[[1]] [1] "o" $i$k$l$n[[2]] [1] "p"
关键逻辑说明
- 递归终止条件:当处理的字符串片段不包含
(或[时,直接返回该字符串,停止递归。 - 嵌套内容分割:使用正则表达式
,(?![^()\\[\\]]*+[)\\]])分割括号内的内容,确保不会错误分割嵌套括号内部的逗号。 - 结果整理:区分无名元素(直接作为列表项)和命名元素(作为带名字的子列表),合并为符合要求的嵌套结构。
内容的提问来源于stack exchange,提问作者Clarinetist
相关产品推荐
相关产品推荐

