2014-06-20 13 views
7

Załóżmy, że mam listy, mówią, że ma trzy poziomy:Usuń NULL element i wyświetlać na liście listy poziomie lokalnym z zagnieżdżonej listy w R

tmp =list(list(list(c(2,9,10), NULL), c(1,3,4,6)), 7) 

co zmieni

[[1]] 
[[1]][[1]] 
[[1]][[1]][[1]] 
[1] 2 9 10 

[[1]][[1]][[2]] 
NULL 

[[1]][[2]] 
[1] 1 3 4 6 

[[2]] 
[1] 7 

chciałbym aby usunąć element NULL i lokalny poziom listy. tj zagnieżdżona lista tmp ma tylko 2 poziomy i staje

tmp =list(list(c(2,9,10), c(1,3,4,6)), 7). 

Oznacza to, że sygnał wyjściowy będzie albo być następujące:

tmp 
[[1]] 
[[1]][[1]] 
[1] 2 9 10 

[[1]][[2]] 
[1] 1 3 4 6 

[[2]] 
[1] 7 

Próbowałem szukać pozycji indeksu NULL ale bez szczęścia. Ponadto nie jestem pewien, jak wykryć i usunąć listę zawierającą element NULL na liście. Dzięki!

Odpowiedz

13

Zazwyczaj usunąć NULL elementów na płaskiej listy z

ll <- list(1, 2, NULL, 3) 
ll <- ll[ ! sapply(ll, is.null) ] 

Jeśli nie znają strukturę z góry, jest to wyraźny przypadek łączenia tego rozwiązania z funkcji rekurencyjnej:

removeNullRec <- function(x){ 
    x <- x[ !sapply(x, is.null) ] 
    if(is.list(x)){ 
    x <- lapply(x, removeNullRec) 
    } 
    return(x) 
} 

removeNullRec(tmp) 

[[1]] 
[[1]][[1]] 
[[1]][[1]][[1]] 
[1] 2 9 10 


[[1]][[2]] 
[1] 1 3 4 6 


[[2]] 
[1] 7 

Edit

To zawsze dobry przeformułowanie problemu tak proste, jak to możliwe. Z twoich komentarzy wynika, że ​​(niezależnie od występowania elementów NULL) chcesz, aby zastąpić każdy element, który zawiera tylko jedno dziecko przez samo dziecko. Jest jeszcze jeden przypadek, który należy wziąć pod uwagę: Dwa liście o rodzeństwie również mogą być NULL. Więc zacznijmy trochę bardziej skomplikowany przykład:

enter image description here

tree <- list(
    list(
    list(
     list(
     list(NULL, NULL), 
     list(NULL, NULL) 
    ), 
     7 
    ), 
    list(
     list(
     list(c(1,2), NULL), 
     c(3,4) 
)))) 

to odosobniony problem płaskiego drzewa jest oczywiście również rozwiązany najlepiej stosując rekurencyjnej podejście:

flatTreeRec <- function(x){ 
    if(is.list(x)){ 
    # recursion 
    x <- lapply(x, flatTree) 
    # remove empty branches 
    x <- x[ sapply(x, length) > 0 ] 
    # flat branches with only child 
    if(length(x) == 1){ 
     x <- x[[1]] 
    } 
    } 
    return(x) 
} 

flatTreeRec(removeNullRec(tree)) 

i Oczywiście możesz bezpośrednio łączyć te dwie funkcje, aby uniknąć dwukrotnego nacisku na swój stos:

removeNullAndFlatTreeRec <- function(x){ 
    x <- x[ !sapply(x, is.null) ] 
    if(is.list(x)){ 
    x <- lapply(x, removeNullRec) 
    x <- x[ sapply(x, length) > 0 ] 
    if(length(x) == 1){ 
     x <- x[[1]] 
    } 
    } 
    return(x) 
} 

removeNullAndFlatTreeRec(tree) 
+0

Dziękuję bardzo! Zastanawiam się, czy lista zawierająca element NULL może być niepubliczna z listy zagnieżdżonej. Dla mojego powyższego przykładu, jeśli na liście zostanie wykryty element NULL, wówczas lista zostanie usunięta, tak że lista zagnieżdżona ma tylko dwie listy. tj. lista (lista (c (2,9,10), c (1,3,4,6)), 7). Twoja funkcja zachowuje taką samą liczbę list, jak na oryginalnej liście. – user2498497

+0

Dzięki!Twój kod działa przy usuwaniu elementu NULL. Jednak nie usuwa/nie wyświetla listy zawierającej element NULL. – user2498497

+0

@ user2498497 w jakich przypadkach chcesz usunąć listę rodzeństwa elementu "NULL"? Tylko jeśli jest to jedyne rodzeństwo i jest płaskie (tzn. Nie zawiera żadnych dzieci)? A co z przypadkami, gdy element listy jest jedynym elementem w hierarchii i jest płaski. Czy chcesz, aby były niepubliczne, chociaż nie ma rodzeństwa "NULL"? Jaki powinien być właściwy wynik 'list (list (list (1,2,3), NULL))'? – Beasterfield

0

używam tej funkcji:

removeNULL <- function(x){ 
    x <- Filter(Negate(is.null), x) 
    if(is.list(x)){ 
     x <- lapply(x, function(y) Filter(length, removeNULL(y))) 
    } 
    return(x) 
} 

Nie tylko usunięcia NULL elementy, ale także usuwa elementy, które znajduje się lista zawierająca jedynie NULL elementów, takich jak A2$A2$format$font w poniższym przykładzie:

> A2 
$A2 
$A2$value 
[1] 9.9 

$A2$format 
$A2$format$numberFormat 
[1] "2Decimal" 

$A2$format$font 
$A2$format$font$name 
NULL 

$A2$format$font$bold 
NULL 

$A2$format$font$color 
NULL 



$A2$comment 
NULL 


> removeNULL(A2) 
$A2 
$A2$value 
[1] 9.9 

$A2$format 
$A2$format$numberFormat 
[1] "2Decimal" 
Powiązane problemy