How to catch integer(0)?

2019-01-21 17:56发布

问题:

Let's say we have a statement that produces integer(0), e.g.

 a <- which(1:3 == 5)

What is the safest way of catching this?

回答1:

That is R's way of printing a zero length vector (an integer one), so you could test for a being of length 0:

R> length(a)
[1] 0

It might be worth rethinking the strategy you are using to identify which elements you want, but without further specific details it is difficult to suggest an alternative strategy.



回答2:

If it's specifically zero length integers, then you want something like

is.integer0 <- function(x)
{
  is.integer(x) && length(x) == 0L
}

Check it with:

is.integer0(integer(0)) #TRUE
is.integer0(0L)         #FALSE
is.integer0(numeric(0)) #FALSE

You can also use assertive for this.

library(assertive)
x <- integer(0)
assert_is_integer(x)
assert_is_empty(x)
x <- 0L
assert_is_integer(x)
assert_is_empty(x)
## Error: is_empty : x has length 1, not 0.
x <- numeric(0)
assert_is_integer(x)
assert_is_empty(x)
## Error: is_integer : x is not of class 'integer'; it has class 'numeric'.


回答3:

Maybe off-topic, but R features two nice, fast and empty-aware functions for reducing logical vectors -- any and all:

if(any(x=='dolphin')) stop("Told you, no mammals!")


回答4:

if ( length(a <- which(1:3 == 5) ) ) print(a)  else print("nothing returned for 'a'") 
#[1] "nothing returned for 'a'"

On second thought I think any is more beautiful than length(.):

 if ( any(a <- which(1:3 == 5) ) ) print(a)  else print("nothing returned for 'a'") 
 if ( any(a <- 1:3 == 5 ) ) print(a)  else print("nothing returned for 'a'") 


回答5:

Inspired by Andrie's answer, you could use identical and avoid any attribute problems by using the fact that it is the empty set of that class of object and combine it with an element of that class:

attr(a,"foo")<-"bar"

> identical(1L,c(a,1L))
[1] TRUE

Or more generally:

is.empty <- function(x, mode=NULL){
    if (is.null(mode)) mode <- class(x)
    identical(vector(mode,1),c(x,vector(class(x),1)))
}

b <- numeric(0)

> is.empty(a)
[1] TRUE
> is.empty(a,"numeric")
[1] FALSE
> is.empty(b)
[1] TRUE
> is.empty(b,"integer")
[1] FALSE