Jeroen Ooms
Jeroen Ooms

Reputation: 32978

Flatten nested list into 1-deep list

I am looking for an efficient solution to (recursively) flatten a nested list (of arbitrary depth) into non-nested, 1 deep list. The list elements are not homogeneous, therefore they should not be unlisted into a vector (that would coerce all values to a single type). The best solution so far is:

flatlist <- function(mylist){
    lapply(rapply(mylist, enquote, how="unlist"), eval)
}

This does almost what I want:

> flatlist(list(foo=TRUE, bar=456, pets=list(cat="meeuw", dog="woof")))
$foo
[1] TRUE

$bar
[1] 456

$pets.cat
[1] "meeuw"

$pets.dog
[1] "woof"

However, a problem is that rapply is dropping NULL values, which is undesired:

> flatlist(list(foo=123, bar=NULL))
$foo
[1] 123

I would like that NULL elements appear in the output, either as NULL or as NA. Also the double loop with enquote and then eval makes things a bit slow. This function is used extensively in my code. Is there a way to do it all in one run?

Upvotes: 6

Views: 2164

Answers (1)

flodel
flodel

Reputation: 89057

Replace the rapply part by your own recursion so NULLs are not getting any special treatment:

renquote <- function(l) if (is.list(l)) lapply(l, renquote) else enquote(l)

lapply(unlist(renquote(ml)), eval)

Upvotes: 8

Related Questions