“&&”的实际用途是什么?和“||” R的运营商?

时间:2014-07-23 22:48:57

标签: r operators logical-operators

主要问题

在实际编程情况或R“习语”中,您只想检查两个向量中每个向量的第一个元素进行逻辑比较吗? (即,忽略每个向量的其余部分,如&&||。)

我可以在R中看到&|的使用,它们在两个向量的元素方式逻辑比较中。但我无法看到他们的同胞操作员&&||的实际使用情况。任何人都可以提供一个明确的使用示例吗?

文档help("&&")说:

  

较长的表单从左到右计算仅检查每个向量的第一个元素。   评估仅在确定结果之前进行。   较长的形式适合   编程控制流程,通常在if子句中使用。

我的问题如下:我解释&&||的文档说明对于逻辑向量xy,{{1} }和&&运算符仅使用||x[1]来提供结果。

y[1]

我没有看到任何“编程控制流”的情况,我会有两个逻辑向量,我会忽略超过每个元素的第一个元素的任何值。

似乎> c(TRUE, FALSE, FALSE) && c(TRUE, FALSE) [1] TRUE > c(TRUE, FALSE, FALSE) && c(FALSE, FALSE) [1] FALSE > c(FALSE, FALSE, FALSE) && c(TRUE, FALSE) [1] FALSE > c(FALSE, FALSE, FALSE) && c(FALSE, FALSE) [1] FALSE 的行为与x && y相似,而x[1] & y[1]的行为似x || y

基准

这是一个测试函数,用于评估这些公式使用随机生成的不同长度的逻辑向量返回相同结果的频率。这表明他们正在做同样的事情。

x[1] | y[1]

收率:

> test <- function( n, maxl=10 ) {
    foo <- lapply( X=seq_len( n ), FUN=function(i) { 
        x <- runif( n=sample( size=1, maxl ) ) > 0.5
        y <- runif( n=sample( size=1, maxl ) ) > 0.5
        sameres <- all.equal( (x||y), (x[1]|y[1]) )
        sameres
    } )

    table( unlist( foo ) )
}
test( 10000 )

这是一个更快的基准测试。首先创建一个列表列表,其中TRUE 10000 中的每个N项都是一个包含两个随机生成的逻辑向量的列表。然后我们在相同数据上应用每个变体,以查看哪个更快。

dat

产生以下输出(删除了library(rbenchmark) N <- 100 maxl <- 10 dat <- lapply( X=seq_len(N), FUN=function(i) { list( runif( n=sample( size=1, maxl ) ) > 0.5, runif( n=sample( size=1, maxl ) ) > 0.5) } ) benchmark( columns=c("test","replications","relative"), lapply(dat, function(L){ L[[1]] || L[[2]] } ), lapply(dat, function(L){ L[[1]][1] | L[[2]][1] } ) ) 个字符和额外的空格):

\n

显然, test replications relative 2 lapply(dat, function(L) { L[[1]][1] | L[[2]][1] }) 100 1.727 1 lapply(dat, function(L) { L[[1]] || L[[2]] }) 100 1.000 公式比樱桃选择每个参数的第一个元素要快。但我仍然很好奇为什么人们需要这样的操作员。

1 个答案:

答案 0 :(得分:3)

我想有几个原因,但最重要的可能是短路行为。如果a评估为FALSE中的a && b,则不会评估b。同样,如果a评估为TRUE中的a || b,则不会评估b。这允许编写像

这样的代码
v <- list(1, 2, 3, 4, 5)
idx <- 6
if (idx < length(v) && v[[idx]] == 5) {
  foo
} else {
  bar
}

否则需要将此(可能)写为

if (idx < length(v)) {
  if (v[idx] == 5) {
    foo
  } else {
    bar
  }
} else {
  bar
}

这是1)更不易阅读,2)重复bar,如果bar是更大的代码,那就不好了。

您无法在&条件中使用if,因为您的索引超出范围,R中的列表不允许这样做:

if (idx < length(v) & v[[idx]] == 5) {
  foo
} else {
  bar
}
# Error in v[[idx]] : subscript out of bounds

以下是短路行为的一个小例子:

t <- function() { print("t called"); TRUE }
f <- function() { print("f called"); FALSE }

f() && t()
# [1] "f called"
# [1] FALSE
f() & t()
# [1] "f called"
# [1] "t called"
# [1] FALSE

t() || f()
# [1] "t called"
# [1] TRUE
t() | f()
# [1] "t called"
# [1] "f called"
# [1] TRUE