2

Assume this simplified example:

L <- list()

L$Foo <- list()
L$Foo$Bar <- list()
L$Foo$Bar$X <- TRUE
L$Foo$Bar$Y <- "abc"

L$Lorem <- list()
L$Lorem$Ipsum <- list()
L$Lorem$Ipsum$Dolor <- list()
L$Lorem$Ipsum$Dolor$X <- TRUE
L$Lorem$Ipsum$Dolor$Z <- "xyz"

In this question, I attempted to recast a nested list of any depth after unlisting it. One answer suggested using unlist() and then relist().

However, this suggestion does not preserve the original classes if they vary. For instance, relist(unlist(L), L) will return:

$Foo
$Foo$Bar
$Foo$Bar$X
[1] "TRUE"

$Foo$Bar$Y
[1] "abc"



$Lorem
$Lorem$Ipsum
$Lorem$Ipsum$Dolor
$Lorem$Ipsum$Dolor$X
[1] "TRUE"

$Lorem$Ipsum$Dolor$Z
[1] "xyz"

Notice that "TRUE" and "FALSE" are erroneously characters, not logicals.

Now, one solution is provided here. However, the answer from this question does not work for any depth level of the nested list. For instance, running relist2(flatten(L), L) as suggested from the answer returns:

> relist2(flatten(L), L)
$Foo
$Foo$Bar.X
$Foo$Bar.X[[1]]
[1] TRUE


$Foo$Bar.Y
$Foo$Bar.Y[[1]]
[1] "abc"



$Lorem
$Lorem$Ipsum.Dolor
$Lorem$Ipsum.Dolor$X
$Lorem$Ipsum.Dolor$X[[1]]
[1] TRUE


$Lorem$Ipsum.Dolor$Z
$Lorem$Ipsum.Dolor$Z[[1]]
[1] "xyz"

Here, the classes are preserved, but not all levels are relisted—notice Ipsum.Dolor that should have been relisted as Ipsum$Dolor.

Any thoughts on how to solve this?

Christian
  • 932
  • 1
  • 7
  • 22

1 Answers1

2

We can use type.convert to change the data types based on the values. unlist coerces the data type to a single one (most probably character if there is a character element) as a vector cannot have multiple data types. The only info available regarding the data type is in the original 'L'. The below code fails if there are custom data types i.e. if the logical value should be actually considered as a different type than logical.

library(magrittr)
L1 <- relist(unlist(L), L) %>% 
     type.convert(as.is = TRUE)

-comparing the structures

 str(L1)
List of 2
 $ Foo  :List of 1
  ..$ Bar:List of 2
  .. ..$ X: logi TRUE
  .. ..$ Y: chr "abc"
 $ Lorem:List of 1
  ..$ Ipsum:List of 1
  .. ..$ Dolor:List of 2
  .. .. ..$ X: logi TRUE
  .. .. ..$ Z: chr "xyz"
> str(L)
List of 2
 $ Foo  :List of 1
  ..$ Bar:List of 2
  .. ..$ X: logi TRUE
  .. ..$ Y: chr "abc"
 $ Lorem:List of 1
  ..$ Ipsum:List of 1
  .. ..$ Dolor:List of 2
  .. .. ..$ X: logi TRUE
  .. .. ..$ Z: chr "xyz"
akrun
  • 874,273
  • 37
  • 540
  • 662