【问题标题】:Removing nested lists of length 0删除长度为 0 的嵌套列表
【发布时间】:2019-07-13 12:32:57
【问题描述】:

我在 R 中有一个列表列表。我想删除长度为零的列表。

到目前为止我尝试过的是:

for (i in 1:length(test)) {
  keep <- rep(T, length(test))
  for (j in 1:length(test[[i]])) {
    if (length(test[[i]][[j]]) == 0) {
      keep[[j]] <- F
    }
  }
  test2[i] <- test2[i][keep]
}

这是一些示例数据(已编辑):

test <- list("Section 1" = list("A" = list(), "B" = list("1x1" = "23", "1x2" = "24"), C = list("2x1" = "78")),
         "Section 2" = list("A" = list(), "B" = list("1x1" = "23", "1x2" = "24"), C = list("2x1" = "78")))

我想要一种方法来删除第 1 节和第 2 节中的“A”列表,因为它们的长度都是 0

【问题讨论】:

  • 我认为这是链接帖子的副本。我不能 100% 确定,因为您不提供示例数据(屏幕截图对于共享数据来说总是一个坏主意)。如果来自欺骗目标的解决方案不能解决您的问题,请澄清您的帖子,包括示例数据,我很乐意重新打开。
  • @MauritsEvers 我添加了一些示例数据,谢谢
  • Filter(function(x) length(x) &gt; 0, test) 适用于您提供的示例数据。
  • @MauritsEvers,不需要匿名函数:Filter(length, test)

标签: r


【解决方案1】:

声称这是重复项需要额外的知识,即仅包含 NULL 项的列表的长度为 0。还需要假设 NULLlist() 是等价的。这些都不一定是显而易见的,尽管用sapply(list(a=NULL), length) 测试该命题显示第一个是这种情况。然而,第二个似乎并非如此。测试:identical(NULL, list()) 返回 FALSE,identical(list(NULL), list())is.null( list() ) 也是如此。

Maurits Evers 的回答应该会成功。这也会成功:

 test <- test[ sapply(test, length) >0] # `sapply will return a logical vector

> test
$B
$B$`1x1`
[1] "23"

$B$`1x2`
[1] "24"


$C
$C$`2x1`
[1] "78"

【讨论】:

  • test[lengths(test)&gt;0]
  • 好一个。我可能曾经知道有一个矢量化版本的length,但如果是这样我就忘记了。
【解决方案2】:

只是为了总结一下,根据我之前的评论,您可以这样做

Filter(function(x) length(x) > 0, test)
#$B
#$B$`1x1`
#[1] "23"
#
#$B$`1x2`
#[1] "24"
#
#
#$C
#$C$`2x1`
#[1] "78"

或者更短(感谢@Parfait)

Filter(length, test)

对于嵌套的list

test <- list("Section 1" = list("A" = list(), "B" = list("1x1" = "23", "1x2" = "24"), C = list("2x1" = "78")), "Section 2" = list("A" = list(), "B" = list("1x1" = "23", "1x2" = "24"), C = list("2x1" = "78")))
lapply(test, function(x) Filter(length, x))
#$`Section 1`
#$`Section 1`$B
#$`Section 1`$B$`1x1`
#[1] "23"
#
#$`Section 1`$B$`1x2`
#[1] "24"
#
#
#$`Section 1`$C
#$`Section 1`$C$`2x1`
#[1] "78"
#
#
#
#$`Section 2`
#$`Section 2`$B
#$`Section 2`$B$`1x1`
#[1] "23"
#
#$`Section 2`$B$`1x2`
#[1] "24"
#
#
#$`Section 2`$C
#$`Section 2`$C$`2x1`
#[1] "78"

【讨论】:

  • 这可以在 for 循环中使用以从每个部分中获取空白列表吗? EX数据:test
  • 不需要显式的for循环@user10256905;只需将Filter 语句包装在lapply 中,请参阅我的编辑。
  • 这要求所有空列表处于同一级别,因为如果您有test$s = list(),lapply 函数将无法捕获此
  • @Onyambu 确实如此。这是 OP 在上面的评论中给出的示例数据。
  • 我仍然认为这是一个重复的帖子。例如对于 NULL 元素的递归删除,请参阅Remove NULL elements from list of lists
【解决方案3】:

您可以编写自己的函数:

check = function(x){
  m = lengths(x)>0
  if(is.list(x[m])) lapply(x[m],check) else x
 }

check(test)
$`Section 1`
$`Section 1`$`B`
$`Section 1`$`B`$`1x1`
[1] "23"

$`Section 1`$`B`$`1x2`
[1] "24"


$`Section 1`$C
$`Section 1`$C$`2x1`
[1] "78"



$`Section 2`
$`Section 2`$`B`
$`Section 2`$`B`$`1x1`
[1] "23"

$`Section 2`$`B`$`1x2`
[1] "24"


$`Section 2`$C
$`Section 2`$C$`2x1`
[1] "78"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    相关资源
    最近更新 更多