简体   繁体   English

从字符串创建嵌套列表结构

[英]Create nested list structure from a string

I have a string that is a composite of n substrings.我有一个由 n 个子字符串组成的字符串。 It could look like this:它可能看起来像这样:

string <- c("A_AA", "A_BB", "A_BB_AAA", "B_AA", "B_BB", "B_CC")

Every subcomponent in this string is separated from any other by "_".此字符串中的每个子组件都以“_”与其他任何子组件分隔。 Here, the first level consists of the values "A" and "B", the second level of "AA", "BB" and "CC", the third level of "AAA".这里,第一级由值“A”和“B”组成,第二级由“AA”、“BB”和“CC”组成,第三级由“AAA”组成。 Deeper nestings are possible and the solution should extend to those cases.更深的嵌套是可能的,解决方案应该扩展到这些情况。 The nestings are not necessarily balanced, eg "A" only has two children, while "B" has three, but it also has a grandchild which "B" has not.嵌套不一定是平衡的,例如“A”只有两个孩子,而“B”有三个,但它也有一个“B”没有的孙子。

Essentially, I want to recreate the nested structure in this string in some kind of R object, preferably a list.本质上,我想在某种 R 对象(最好是列表)中重新创建此字符串中的嵌套结构。 Thus, the nested list structure that would look like this:因此,嵌套列表结构如下所示:

list("A" = list("AA", "BB" = list("AAA")),
"B" = list("AA", "BB", "CC"))

> $A
  $A[[1]]

  [1] "AA"
  $A$BB
  $A$BB[[1]]
  [1] "CCC"

  $B
  $B[[1]]
  [1] "AA"

  $B[[2]]
  [1] "BB"

  $B[[3]]
  [1] "CC"

Any help on this is appreciated对此的任何帮助表示赞赏

You can make it into a matrix without too much fuss...你可以把它变成一个矩阵而不必大惊小怪......

string <- c("A_AA", "A_BB", "A_BB_AAA", "B_AA", "B_BB", "B_CC")

splitted<-strsplit(string,"_")
cols<-max(lengths(splitted))
mat<-do.call(rbind,lapply(splitted, "length<-", cols))

Not so straight forward, also not the most beautiful code, but it should do its job and return a list:不是那么直接,也不是最漂亮的代码,但它应该完成它的工作并返回一个列表:

string <- c("A_AA", "A_BB", "A_BB_AAA", "B_AA", "B_BB", "B_CC")

# loop through each element of the string "str_el"
list_els <- lapply(string, function(str_el) {

  # split the string into parts
  els <- strsplit(str_el, "_")[[1]]

  # loop backwards through the elements
  for (i in length(els):1){

    # the last element gives the value
    if (i == length(els)){

      # assign the value to a list and rename the list          
      res <- list(els[[i]])
      names(res) <- els[[i - 1]]

    } else {
      # if its not the last element (value) assign the list res to another list
      # with the name of that element
      if (i != 1) {
        res <- list(res)
        names(res) <- els[[i - 1]]
      }
    }
  }

  return(res)
})

# combine the lists into one list
res_list <- mapply(c, list_els, SIMPLIFY = F)

res_list
# [[1]]
# [[1]]$A
# [1] "AA"
# 
# 
# [[2]]
# [[2]]$A
# [1] "BB"
# 
# 
# [[3]]
# [[3]]$A
# [[3]]$A$BB
# [1] "AAA"
# 
# 
# 
# [[4]]
# [[4]]$B
# [1] "AA"
# 
# 
# [[5]]
# [[5]]$B
# [1] "BB"
# 
# 
# [[6]]
# [[6]]$B
# [1] "CC"

Does that give you what you want?这给你你想要的吗?

I found this way to do it.我找到了这种方法。 It's weird, but seems to work这很奇怪,但似乎有效

my_relist <- function(x){
y=list()
#This first loop creates the skeleton of the list
for (name in x){
    split=strsplit(name,'_',fixed=TRUE)[[1]]
    char='y'
    l=length(split)
    for (i in 1:(l-1)){
        char=paste(char,'$',split[i],sep="")
    }
char2=paste(char,'= list()',sep="")
#Example of char2: "y$A$BB=list()"
eval(parse(text=char2))
#Evaluates the expression inside char2
}

#The second loop fills the list with the last element
for (name in x){
   split=strsplit(name,'_',fixed=TRUE)[[1]]
   char='y'
   l=length(split)
   for (i in 1:(l-1)){
       char=paste(char,'$',split[i],sep="")
   }
char3=paste(char,'=c(',char,',split[l])')
#Example of char3: "y$A = c(y$A,"BB")"
eval(parse(text=char3))
}
return(y)
}

And this is the result:这是结果:

example <- c("A_AA_AAA", "A_BB", "A_BB_AAA", "B_AA", "B_BB", "B_CC")
my_relist(example)
#$A
#$BB
#1.'AAA'
#[[2]]
#'AA'
#[[3]]
#'BB'
#$B
#1.'AA'
#2.'BB'
#3.'CC'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM