2016-09-29 65 views
0

数学Which功能的是广义If等效Mathematica的哪

Which[test_1, value_1, test_2, value_2, …]

评估每个依次test_i的,返回value_i的对应于所述第一个中的值,该值产量为True

这只不过是一种方便的方式来摆脱嵌套简单的if-else测试的长序列中的多余语法。

R是否具有相同的功能?


顺便说一句,我知道,我总是可以这样做

if (test_1) value_1 else if (test_2) value_2 else ... value_n else default 

,或者等价地,

if (test_1) value_1 else 
if (test_2) value_2 else 
      ... 
if (test_n) value_n else 
      default 

...但是,正如我已经提到,相比于当Which,嵌套的if-else语句带来了很多多余的语法。

而且,我所知道的

ifelse(t_1, v_1, ifelse(t_2, v_2, ..., ifelse(t_n, v_n, default)...)) 

...但结果到测试的形状敏感,所以它不完全等同于嵌套if-else语句。

最后,R的switch声明与我正在寻找的声明类似,因为它将一个调度封装在一系列测试中,但它并不完全相同。在

switch(expr, 
     case_1 = value_1, 
     case_2 = value_2, 
     ... 
     case_n = value_n, 
     default) 

...测试是expr人人平等的比较对case_i,而在Which等,测试是任意的布尔表达式。

+0

@JohnColeman:因为,AFAICT,'case_i'必须是标签;他们不能是任意的表达......(我可能错了) – kjo

+0

@kjo你是对的。 –

+0

@ZheyuanLi:尽管他们的名字,R的''哪个'功能和Mathematica的'哪个'做了很不同的事情。 – kjo

回答

1

你可以编写自己的函数,可以用作这样的控制结构。其次是基于match.call支持懒惰评估的事实。 (见this接受的答案):

which.val <- function(...){ 
    clauses <- match.call(expand.dots = FALSE)$`...` 
    n <- length(clauses) 
    for(i in seq(1,n,2)){ 
    condition = eval(clauses[[i]], envir = parent.frame()) 
    if(condition) return(eval(clauses[[i+1]], envir = parent.frame())) 
    } 
} 

出于测试目的:

test <- function(a,b){ 
    print(b) 
    a == b 
} 

的副作用可以用来看看什么是真正评估。

例如:

> x <- 3 
> which.val(test(x,1),10,test(x,2),20,test(x,3),30,test(x,4),40) 
[1] 1 
[1] 2 
[1] 3 
[1] 30 

test(x,4)是如何从不评价。

+0

没错。谢谢。我不知道R对用户定义函数中懒惰评估的支持。那很棒。 – kjo

+0

问题:你不想要'return(eval(子句[[i + 1]]))? – kjo

+0

你说得对。我用恒定的值测试它,它工作正常,但你不想返回一个未评估的表达式。我改变了我的例子,以便返回值看起来像'x + 10'而不是'10'等,我的代码没有返回预期的值。我将编辑。谢谢。 –

3

按照Mathematica的帮助下,

其中[test1的,值1,测试2,值2,...]评估每个依次TESTI的,返回valuei对应的第一个的值产量为真。

我们可以在R,即做到这一点得到对应值为true第一表达的位置值,像这样的:评估所有表达式

1.简单的版本:

values = c("value1", "value2", "value3", "value4", "value5", "value6", "value7") 
expressions = c(1==2, 1==3, 1==1, 1==4, T==F, F==T, T==T) 
values[which.max(expressions)] 
# [1] "value3" 

虽然没有一个表达式是真的,马克斯将返回第一个假的,所以我们也应该检查这个

if (any(expressions)) values[which.max(expressions)] else NA 

2版本的“短路”

然而,在上述的数学从行为的一个区别是: which在mathematica短路 - 即它只评估尽可能多的表达式,因为它需要找到第一个TRUE。如果表达式在计算上很昂贵或速度瓶颈,那么我们也可能喜欢在R中复制这种行为。我们可以使用Position做短路,并结合eval(parse)来确保我们不评估表达式,直到我们准备好为他们测试

values = c("value1", "value2", "value3", "value4", "value5", "value6", "value7") 
expressions = c("1==2", "1==3", "1==1", "1==4", "T==F", "F==T", "T==F") 

values[Position(function(text) eval(parse(text=text)), expressions, T)]