2016-09-29 62 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)]