Home > Blockchain >  Assigning the name in a nested list to it's subcomponents
Assigning the name in a nested list to it's subcomponents

Time:04-18

I have a nested list current_output that I would like to unlist and obtain the expected output. I would like to assign the name of the list in current_output to it's sub-components. For example, I would like to assign the name A to the three sub-components in current_output, and similarly for B and C to match those in the `expected.

A1 <- c(1:3)
A2 <- c(4:6)
A3 <- c(7:9)
B1 <- c(1:2)
B2 <- c(3:4)
B3 <- 1
C1 <- c(1:3)
C2 <- 1
C3 <- 1

l1 <- list(list(A1), list(A2), list(A3))
l2 <- list(list(B1),list(B2), list(1))
l3 <- list(list(C1), list(1), list(1))

current_output <- list(l1, l2, l3)
names(current_output) <- c("A", "B", "C")


expected <- list(A1, A2, A3, B1, B2, B3, C1, C2, C3)
names(expected) <- c(rep("A", 3), rep("B", 3), rep("C", 3))

CodePudding user response:

It is better to have unique key i.e. names for the list elements - loop over the nested list, flatten, then invoke by concatenating again, and change the names by removing the suffix digits from the names

library(purrr)
library(dplyr)
library(stringr)
out <- current_output %>% 
   map(flatten) %>%   
   invoke(c, .) %>%  
   setNames(str_remove(names(.), "\\d "))

-testing

> all.equal(out, expected)
[1] TRUE

Or another option is rrapply

rrapply::rrapply(current_output, how = 'flatten') %>% 
    setNames(rep(names(current_output), lengths(current_output)))

Or using base R, unlist the list elements, convert each element to list element with as.list and then remove the digits from the names with sub and assign back the names

out <- as.list(unlist(current_output))
names(out) <- sub("\\d $", "", names(out))

CodePudding user response:

Another base R approach that uses multiple unlist() steps.

setNames(
  unlist(current_output, recursive = F) %>% unlist(recursive = F), 
  rep(names(current_output), each = 3)
  )

Output

$A
[1] 1 2 3

$A
[1] 4 5 6

$A
[1] 7 8 9

$B
[1] 1 2

$B
[1] 3 4

$B
[1] 1

$C
[1] 1 2 3

$C
[1] 1

$C
[1] 1

CodePudding user response:

Another possible solution:

library(tidyverse)

current_output %>% imap(set_names) %>% flatten %>% flatten

#> $A
#> [1] 1 2 3
#> 
#> $A
#> [1] 4 5 6
#> 
#> $A
#> [1] 7 8 9
#> 
#> $B
#> [1] 1 2
#> 
#> $B
#> [1] 3 4
#> 
#> $B
#> [1] 1
#> 
#> $C
#> [1] 1 2 3
#> 
#> $C
#> [1] 1
#> 
#> $C
#> [1] 1
  • Related