【问题标题】:Convert a string with curly brackets to a nested list object将带大括号的字符串转换为嵌套列表对象
【发布时间】:2020-11-16 17:26:59
【问题描述】:

我们有一个带大括号的字符串来表示嵌套列表:

x <- "{{1,2,3,4},{1,2,3,4,{Axe,Bat,Cat,Donkey}},{1,2,3,4}}"

我们如何将其转换为嵌套列表R对象?

到目前为止,我有以下解决方案,它并不理想。想法是将其转换为有效的 JSON 格式,然后使用jsonlite::fromJSON。我想跳过/改进引用步骤,以便读取的数字是数字。是的,我可以遍历嵌套列表并将"numbers" 转换为数字,但我想避免。

也欢迎任何其他非 JSON 解决方案。

library(jsonlite)

# translate brackets to JSON square brackets
x <- chartr("{}", "[]", x)

# wrap in quotes
x <- gsub("(\\w+)", '"\\1"', x)

# finally read as JSON
fromJSON(x)

# [[1]]
# [1] "1" "2" "3" "4"
# 
# [[2]]
# [[2]][[1]]
# [1] "1"
# 
# [[2]][[2]]
# [1] "2"
# 
# [[2]][[3]]
# [1] "3"
# 
# [[2]][[4]]
# [1] "4"
# 
# [[2]][[5]]
# [1] "Axe" "Bat" "Cat" "Donkey"
# 
# 
# [[3]]
# [1] "1" "2" "3" "4"

【问题讨论】:

  • 你不能用[A-Z] 代替w 做一个gsub 吗? (我不掌握正则表达式)
  • @StéphaneLaurent 同样在这里,不是正则表达式大师,好的,这比我想象的要简单,随时添加为答案。
  • @StéphaneLaurent 哦,不,抱歉,输入不是单个字母。这只是一个例子,它们可以不止一个字母。
  • 我更愿意将答案留给正则表达式大师 :)
  • 是的,但[A-Z]+ 应该适用于多个字母(或类似的东西)。

标签: r json regex jsonlite


【解决方案1】:

此解决方案不使用任何软件包。它将最里面的列表替换为c(...),然后引用以字母开头的单词,并将{} 分别替换为list()。然后它解析并评估它以获得结果。

x1 <- gsub("\\{([^{]+)\\}", "c(\\1)", x) # x is from question
x2 <- gsub("([a-zA-Z]\\w+)", "'\\1'", x1)
x3 <- gsub("\\{", "list(", x2)
x4 <- gsub("\\}", ")", x3)
result <- eval(parse(text = x4))

str(result)

给予:

List of 3
 $ : num [1:4] 1 2 3 4
 $ :List of 5
  ..$ : num 1
  ..$ : num 2
  ..$ : num 3
  ..$ : num 4
  ..$ : chr [1:4] "Axe" "Bat" "Cat" "Donkey"
 $ : num [1:4] 1 2 3 4

这也可以用 magrittr 写成管道:

library(magrittr)

x %>%
  gsub("\\{([^{]+)\\}", "c(\\1)", .)  %>%
  gsub("([a-zA-Z]\\w+)", "'\\1'", .) %>%
  gsub("\\{", "list(", .) %>%
  gsub("\\}", ")", .) %>%
  parse(text = .) %>%
  eval

【讨论】:

  • “不使用任何包”谢谢。我也在考虑 gsub+eval+parse,但未能应用正确的正则表达式。
【解决方案2】:

你可以这样做:

jsonlite::fromJSON(txt=gsub('([A-Za-z]+)','"\\1"',chartr('{}','[]',x)))
[[1]]
[1] 1 2 3 4

[[2]]
[[2]][[1]]
[1] 1

[[2]][[2]]
[1] 2

[[2]][[3]]
[1] 3

[[2]][[4]]
[1] 4

[[2]][[5]]
[1] "Axe"    "Bat"    "Cat"    "Donkey"


[[3]]
[1] 1 2 3 4

或者你可以使用alpha 即:

jsonlite::fromJSON(txt=gsub('([[:alpha:]]+)','"\\1"',chartr('{}','[]',x)))

这里的问题是获得一个好的正则表达式,使其不包含数字元素。

【讨论】:

    猜你喜欢
    • 2012-01-28
    • 2014-06-04
    • 2022-12-10
    • 2016-02-08
    • 1970-01-01
    • 2023-03-31
    • 2021-11-25
    • 2019-04-24
    • 1970-01-01
    相关资源
    最近更新 更多