以下のように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"))
この再帰的なソリューションには、さらに深くネストされたリストで作業するという利点があります。
これは、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"
Filter
とNegate
の組み合わせを使用したオプション
Filter(Negate(function(x) is.null(unlist(x))), lll)
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
この特定の例では、unlist
引数とともにrecursive
を使用することもできます。
lll[!sapply(unlist(lll, recursive=FALSE), is.null)]
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
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"
リストにはリストがあるので、おそらく次のようにl/sapply
を2回実行する必要があります。
lll[!sapply(lll,sapply,is.null)]
#[[1]]
#[[1]][[1]]
#[1] 1
#
#
#[[2]]
#[[2]][[1]]
#[1] "a"
CRANには新しいパッケージrlistがあります。KunRenは私たちの生活を楽にしてくれました。
list.clean(.data, fun = is.null, recursive = FALSE)
またはNULLを再帰的に削除する場合:
list.clean(.data, fun = is.null, recursive = TRUE)
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)
}
}