2015-07-11 18 views

Odpowiedz

13

Oto rekurencyjna realizacja:

flatten2 <- function(X) if(is.list(X)) Reduce(c, lapply(X, flatten2)) else list(X) 

Następnie:

str(flatten2(B)) # list of three matrices: 
# List of 3 
# $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10 
# $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10 
# $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10 

i bardziej złożone:

C <- list(A, list(list(A, A), A)) 
str(flatten2(C)) 
# List of 4 
# $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10 
# $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10 
# $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10 
# $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10 

Również "wordier", ale szybsza wersja (ta jest testowana przez P ierre):

flatten <- function(X) { 
    res <- list() 
    for(i in X) res <- c(res, if(is.list(i)) Recall(i) else list(i)) 
    res 
} 

Można też zrobić flatten2 trochę szybciej zastępując Reduce z do.call, ale to jest trochę mniej słodkie. flatten pozostaje najszybszy nawet po tej zmianie.

+0

Twoje rozwiązanie może być najszybsze. –

11

Można zrobić coś takiego

delist<-function(x) { 
    lists <- sapply(x, class)=="list" 
    while(any(lists)) { 
     x<-mapply(function(y,z) if (!z) list(y) else (y), x, lists, SIMPLIFY=FALSE) 
     x<-do.call('c', x) 
     lists <- sapply(x, class)=="list" 
    } 
    x 
} 

ze swoim przykładzie masz

delist(B) 
# [[1]] 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] 1 3 5 7 9 
# [2,] 2 4 6 8 10 
# 
# [[2]] 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] 1 3 5 7 9 
# [2,] 2 4 6 8 10 
# 
# [[3]] 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] 1 3 5 7 9 
# [2,] 2 4 6 8 10 
+0

Zastanawiam się, czy to może być dostosowane do pracy z dodatkowym poziomem zagnieżdżenia jak 'B = list (A, listy (A, list (A))) ' –

+1

@PierreLafortune Zaktualizowałem, aby dodać słowo" SIMPLIFY = FALSE ", które powinno teraz działać. Zapobiega to niepożądanemu uproszczeniu, które było przyczyną problemu. – MrFlick

+1

Lub możesz użyć 'Map'! ;) (+1) – BrodieG

7

Można użyć funkcji list.flatten pakietu rlist. Przykład:

library(rlist) 
A1 <- matrix(1:10, nrow = 2) 
A2 <- matrix(11:20, nrow = 2) 
A3 <- matrix(21:30, nrow = 2) 
B <- list(A1, list(A2, A3)) 
C <- list.flatten(B) 

C  
# [[1]] 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] 1 3 5 7 9 
# [2,] 2 4 6 8 10 
# 
# [[2]] 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] 11 13 15 17 19 
# [2,] 12 14 16 18 20 
# 
# [[3]] 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] 21 23 25 27 29 
# [2,] 22 24 26 28 30 

str(C)  
# List of 3 
# $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10 
# $ : int [1:2, 1:5] 11 12 13 14 15 16 17 18 19 20 
# $ : int [1:2, 1:5] 21 22 23 24 25 26 27 28 29 30 
+1

Co za interesujący pakiet. +1 Dobrze wiedzieć –

+0

@PierreLafortune, to mój ulubiony pakiet do pracy z listą. – AndreyAkinshin

5

Tyle świetnych rozwiązań. Chciałem przyczynić się do porównania:

library(microbenchmark) 
microbenchmark(
    flatten = flatten(lst), 
    delist = delist(lst), 
    list.flatten = list.flatten(lst)) 
#   expr  min  lq  mean median  uq 
#  flatten 14.606 16.3830 19.17356 17.7640 18.5540 
#  delist 228.559 239.6115 251.52930 247.5070 254.0205 
# list.flatten 51.318 56.0545 63.87871 61.7785 70.2660 
#  max neval 
# 41.449 100 
# 406.589 100 
# 145.267 100 

danych

A <- matrix(1e4, 100) 
lst <- list(A, list(A, list(A, list(A, list(A, list(A, list(A))))))) 
flatten <- function(X) { 
    res <- list() 
    for(i in X) res <- c(res, if(is.list(i)) Recall(i) else list(i)) 
    res 
} 

delist<-function(x) { 
    lists <- sapply(x, class)=="list" 
    while(any(lists)) { 
     x<-mapply(function(y,z) if (!z) list(y) else (y), x, lists, SIMPLIFY=FALSE) 
     x<-do.call('c', x) 
     lists <- sapply(x, class)=="list" 
    } 
    x 
} 
library(rlist) 
list.flatten