R:如何在属性的嵌套列表中设置名称

时间:2016-03-07 09:58:42

标签: r list nested attr

编辑:我重写了这个问题,因为我有两个相关的问题可能会更好地一起回答......

我有一些大型嵌套list,结构几乎相同,没有名字。 list的所有项目都有attr个ibutes,我想在list的所有级别中将这些项目指定为名称。此外,我想删除一个不必要的列表级别。

所以这个:

before <- list(list("value_1"), list(list("value_2a"), list("value_2b")), list(list("value_3a"), list("value_3b"), list("value_3c")), list("value_4"))
for(i in 1:4) attr(before[[i]], "tag") <- paste0("tag_", i)
attr(before[[2]][[1]], "code") <- "code_2a"
attr(before[[2]][[2]], "code") <- "code_2b"
attr(before[[3]][[1]], "code") <- "code_3a"
attr(before[[3]][[2]], "code") <- "code_3b"
attr(before[[3]][[3]], "code") <- "code_3c"
str(before)
## List of 4
##  $ :List of 1
##   ..$ : chr "value_1"
##   ..- attr(*, "tag")= chr "tag_1"
##  $ :List of 2
##   ..$ :List of 1
##   .. ..$ : chr "value_2a"
##   .. ..- attr(*, "code")= chr "code_2a"
##   ..$ :List of 1
##   .. ..$ : chr "value_2b"
##   .. ..- attr(*, "code")= chr "code_2b"
##   ..- attr(*, "tag")= chr "tag_2"
##  $ :List of 3
##   ..$ :List of 1
##   .. ..$ : chr "value_3a"
##   .. ..- attr(*, "code")= chr "code_3a"
##   ..$ :List of 1
##   .. ..$ : chr "value_3b"
##   .. ..- attr(*, "code")= chr "code_3b"
##   ..$ :List of 1
##   .. ..$ : chr "value_3c"
##   .. ..- attr(*, "code")= chr "code_3c"
##   ..- attr(*, "tag")= chr "tag_3"
##  $ :List of 1
##   ..$ : chr "value_4"
##   ..- attr(*, "tag")= chr "tag_4"

(注意:第一级列表项具有“标记” - 属性,第二级项目具有“代码” - 属性。)

应该是这样的:

after <- list(tag_1="value_1", tag_2=list(code_2a="value_2a", code_2b="value_2b"), tag_3=list(code_3a="value_3a", code_3b="value_3b", code_3c="value_3c"), tag_4="value_4")
str(after)
## List of 4
##  $ tag_1: chr "value_1"
##  $ tag_2:List of 2
##   ..$ code_2a: chr "value_2a"
##   ..$ code_2b: chr "value_2b"
##  $ tag_3:List of 3
##   ..$ code_3a: chr "value_3a"
##   ..$ code_3b: chr "value_3b"
##   ..$ code_3c: chr "value_3c"
##  $ tag_4: chr "value_4"

由于列表很大,我想避免for循环,以获得更好的性能。

2 个答案:

答案 0 :(得分:0)

您可以通过在列表中递归来轻松完成此操作。试试这个:

setListNames <- function(mylist){
  # Base case: if we have a nonlist object, set name to its attribute
  if( !is.list(mylist) ){
    names( mylist ) = attr(mylist, 'code')
    return( mylist )
  }

  # lapply through all sublists and recursively call
  mylist = lapply(mylist, setListNames)

  # Return named list
  return( mylist )
}

# Test run
before_named = setListNames(before)
# Check it worked
print( names( before_named[[2]][[1]][[1]] ) )

答案 1 :(得分:0)

知道了!三个步骤,但效果很好。

# the ugly list
ugly_list <- list(list("value_1"), list(list("value_2a"), list("value_2b")), list(list("value_3a"), list("value_3b"), list("value_3c")), list("value_4"))
for(i in 1:4) attr(ugly_list[[i]], "tag") <- paste0("tag_", i)
attr(ugly_list[[2]][[1]], "code") <- "code_2a"
attr(ugly_list[[2]][[2]], "code") <- "code_2b"
attr(ugly_list[[3]][[1]], "code") <- "code_3a"
attr(ugly_list[[3]][[2]], "code") <- "code_3b"
attr(ugly_list[[3]][[3]], "code") <- "code_3c"

# set names for 1st level 
level_1_named <- setNames(ugly_list, sapply(ugly_list, function(x) attributes(x)$tag))

# set names for 2nd level
level_2_named <- lapply(level_1_named, function(x) lapply(x, function(y) setNames(y, attributes(y)$code)))

# clean list
clean_list <- lapply(level_2_named, function(x) unlist(x, recursive=FALSE))

感谢您的努力。 : - )