web-dev-qa-db-ja.com

リストのリストからNULL要素を削除する

以下のようにRのリストのリストからnull要素を削除するにはどうすればよいですか?

lll <- list(list(NULL),list(1),list("a"))

私が欲しいオブジェクトは次のようになります。

lll <- list(list(1),list("a"))

私はここで同様の答えを見ました: リストから要素を削除するにはどうすればよいですか? しかし、単純なリストからリストのリストに要素を拡張できませんでした。

編集

私の側の上記の悪い例。どちらの答えも、単純なケース(上記)で機能します。リストが次のような場合:

lll <- list(list(NULL),list(1,2,3),list("a","b","c"))

取得する方法:

lll <- list(list(1,2,3),list("a","b","c"))
32
Chris

この再帰的なソリューションには、さらに深くネストされたリストで作業するという利点があります。

これは、Gabor Grothendieckの この非常によく似た質問 に対する答えに密接にモデル化されています。必要に応じて、関数がlist(NULL)NULLとは異なります)などのオブジェクトも削除する場合、そのコードを変更する必要があります。

## A helper function that tests whether an object is either NULL _or_ 
## a list of NULLs
is.NullOb <- function(x) is.null(x) | all(sapply(x, is.null))

## Recursively step down into list, removing all such objects 
rmNullObs <- function(x) {
   x <- Filter(Negate(is.NullOb), x)
   lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
}

rmNullObs(lll)
# [[1]]
# [[1]][[1]]
# [1] 1
# 
# 
# [[2]]
# [[2]][[1]]
# [1] "a"

以下に、より深くネストされたリストへのアプリケーションの例を示します。現在提案されている他のソリューションでは、さまざまな失敗が生じます。

LLLL <- list(lll)
rmNullObs(LLLL)
# [[1]]
# [[1]][[1]]
# [[1]][[1]][[1]]
# [[1]][[1]][[1]][[1]]
# [1] 1
# 
# 
# [[1]][[1]][[2]]
# [[1]][[1]][[2]][[1]]
# [1] "a"
26
Josh O'Brien

FilterNegateの組み合わせを使用したオプション

Filter(Negate(function(x) is.null(unlist(x))), lll)
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
21
David Arenburg

この特定の例では、unlist引数とともにrecursiveを使用することもできます。

lll[!sapply(unlist(lll, recursive=FALSE), is.null)]
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
7
Rich Scriven

purrrを使用する

purrr::map(lll, ~ purrr::compact(.)) %>% purrr::keep(~length(.) != 0)
[[1]]
[[1]][[1]]
[1] 1

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

[[1]][[3]]
[1] 3


[[2]]
[[2]][[1]]
[1] "a"

[[2]][[2]]
[1] "b"

[[2]][[3]]
[1] "c"
7
Leni Ohnesorge

リストにはリストがあるので、おそらく次のようにl/sapplyを2回実行する必要があります。

lll[!sapply(lll,sapply,is.null)]

#[[1]]
#[[1]][[1]]
#[1] 1
#
#
#[[2]]
#[[2]][[1]]
#[1] "a"
5
thelatemail

CRANには新しいパッケージrlistがあります。KunRenは私たちの生活を楽にしてくれました。

    list.clean(.data, fun = is.null, recursive = FALSE)

またはNULLを再帰的に削除する場合:

    list.clean(.data, fun = is.null, recursive = TRUE)
4
Raminsu

Josh O'Brienのソリューションの簡単な修正。関数のリストには少し問題があります

is.NullOb <- function(x) if(!(is.function(x))) is.null(x) | all(sapply(x, is.null)) else FALSE

## Recursively step down into list, removing all such objects 
rmNullObs <- function(x) {
  if(!(is.function(x))) {
    x = x[!(sapply(x, is.NullOb))]
    lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
  }
}
0
bramtayl