从列表中提取非 null 元素

Extract non null elements from a list

提问人:qed 提问时间:6/3/2013 最后编辑:zx8754qed 更新时间:5/23/2023 访问量:24808

问:

我有一个这样的列表:

    x = list(a = 1:4, b = 3:10, c = NULL)
    x
    #$a
    #[1] 1 2 3 4
    #
    #$b
    #[1]  3  4  5  6  7  8  9 10
    #
    #$c
    #NULL

我想提取所有非 null 的元素。这怎么能做到?谢谢。

r 数据操作

评论


答:

13赞 csgillespie 6/3/2013 #1

怎么样:

x[!unlist(lapply(x, is.null))]

以下是正在发生的事情的简要描述。

  1. lapply告诉我们哪些元素是NULL

    R> lapply(x, is.null)
    $a
    [1] FALSE
    
    $b
    [1] FALSE
    
    $c
    [1] TRUE
    
  2. 接下来,我们将列表对流成一个向量:

    R> unlist(lapply(x, is.null)) 
    a     b     c 
    FALSE FALSE  TRUE 
    
  3. 然后我们切换到:TRUEFALSE

    R> !unlist(lapply(x, is.null))
        a     b     c 
    TRUE  TRUE FALSE 
    
  4. 最后,我们使用通常的符号选择元素:

    x[!unlist(lapply(x, is.null))]
    

评论

7赞 Julius Vainora 6/3/2013
不会更快吗?x[!sapply(x, is.null)]
50赞 Matthew Plourde 6/3/2013 #2

这是另一种选择:

Filter(Negate(is.null), x)
1赞 Sander 12/13/2015 #3

以下方法比上述方法更简单,可能更快,适用于任何非递归(在意义上)值的列表:is.recursive

example_1_LST <- list(NULL, a=1.0, b=Matrix::Matrix(), c=NULL, d=4L)
example_2_LST <- as.list(unlist(example_1_LST, recursive=FALSE))

str(example_2_LST)指纹:

List of 3
 $ a: num 1
 $ b:Formal class 'lsyMatrix' [package "Matrix"] with 5 slots
  .. ..@ x       : logi NA
  .. ..@ Dim     : int [1:2] 1 1
  .. ..@ Dimnames:List of 2
  .. .. ..$ : NULL
  .. .. ..$ : NULL
  .. ..@ uplo    : chr "U"
  .. ..@ factors : list()
 $ d: int 4

评论

0赞 Rich Scriven 12/13/2015
您不需要使用 和 引用 base 和 utils 中的函数。base::utils::
13赞 ColinTea 8/6/2016 #4
x[!sapply(x,is.null)]

这概括到有关列表的任何逻辑语句,只是在“is.null”的逻辑中插入。

1赞 GKi 5/23/2023 #5

一个选项是使用 。%in%

x[!x %in% list(NULL)]
#$a
#[1] 1 2 3 4
#
#$b
#[1]  3  4  5  6  7  8  9 10

或者在 .is.nullvapply

x[!vapply(x, is.null, FALSE)]

或者使用 ,但如果列表包含例如 .lengthsnumeric(0)

x[lengths(x) > 0]

基准

x = list(a = 1:4, b = 3:10, c = NULL)
bench::mark(
sapply = x[!sapply(x,is.null)],
Filter = Filter(Negate(is.null), x),
"in" = x[!x %in% list(NULL)],
lapply = x[!unlist(lapply(x, is.null))],
vapply = x[!vapply(x, is.null, FALSE)],
lengths = x[lengths(x) > 0] )
#  expression     min  median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time
#  <bch:expr> <bch:t> <bch:t>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm>
#1 sapply     19.85µs 22.73µs    40853.        0B    12.3   9997     3    244.7ms
#2 Filter     11.84µs 13.73µs    70067.        0B    14.0   9998     2    142.7ms
#3 in          9.87µs 11.45µs    81415.        0B     8.14  9999     1    122.8ms
#4 lapply       6.4µs  7.49µs   126673.        0B    12.7   9999     1     78.9ms
#5 vapply      4.64µs  5.51µs   177842.        0B    17.8   9999     1     56.2ms
#6 lengths     2.12µs  2.32µs   414271.        0B     0    10000     0     24.1ms

评论

0赞 Yoann Pageaud 9/30/2023
实际上,对于软件包开发,vapply() 可能应该按照您在此处的建议使用。我实际上会写得有点不同。见下文:不知道它与使用有多大不同,也不知道它是否对基准测试有影响。有什么想法吗?x[!vapply(x, is.null, logical(length = 1L))]FALSE
1赞 GKi 10/1/2023
logical(length = 1L)给。在基准测试中,我不希望有区别。FALSE