You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将含括号与圆括号的字符串转换为嵌套列表

嵌套括号字符串转嵌套列表的递归实现方案

需求说明

需要将以下字符串转换为指定结构的嵌套列表:

原字符串:

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"

关键逻辑说明

  1. 递归终止条件:当处理的字符串片段不包含(或[时,直接返回该字符串,停止递归。
  2. 嵌套内容分割:使用正则表达式,(?![^()\\[\\]]*+[)\\]])分割括号内的内容,确保不会错误分割嵌套括号内部的逗号。
  3. 结果整理:区分无名元素(直接作为列表项)和命名元素(作为带名字的子列表),合并为符合要求的嵌套结构。

内容的提问来源于stack exchange,提问作者Clarinetist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 13:10:38