2010-11-15 33 views
3

我想的功能AnyTrue[expr,{i,{i1,i2,...}}]其中檢查是否exprTrue任何的i1,i2...它應該是彷彿AnyTrue其次[email protected]@%Table,不同之處在於它只有評估expr,直到找到第一個True自定義函數(行爲類似於表)

短路部分是可選的,我真的很想知道的是正確的方法來模擬Table的非標準評估序列。

更新11/14

這裏有一個解決方案,由於邁克爾,你可以用它來鏈「所有」和「存在」檢查

SetAttributes[AllTrue, HoldAll]; 
SetAttributes[AnyTrue, HoldAll]; 
AllTrue[{var_Symbol, lis_List}, expr_] := 
    LengthWhile[lis, 
    TrueQ[ReleaseHold[Hold[expr] /. HoldPattern[var] -> #]] &] == 
    Length[lis]; 
AnyTrue[{var_Symbol, lis_List}, expr_] := 
    LengthWhile[lis, 
    Not[TrueQ[ReleaseHold[Hold[expr] /. HoldPattern[var] -> #]]] &] < 
    Length[lis]; 
AllTrue[{a, {1, 3, 5}}, AnyTrue[{b, {2, 4, 5}}, EvenQ[a + b]]] 
AnyTrue[{a, {1, 3, 5}}, AllTrue[{b, {2, 4, 5}}, EvenQ[a + b]]] 

回答

5

這個怎麼樣?

SetAttributes[AnyTrue, HoldAll]; 

AnyTrue[expr_, {var_Symbol, lis_List}] := 
    LengthWhile[lis, 
    Not[TrueQ[ReleaseHold[Hold[expr] /. HoldPattern[var] -> #]]] & 
    ] < Length[lis] 

通過LengthWhile包括短路,並且一直保持在必要的一切,讓事情按預期工作與var所具有的功能之外的值:

In[161]:= x = 777; 

In[162]:= AnyTrue[Print["x=", x]; x == 3, {x, {1, 2, 3, 4, 5}}] 
During evaluation of In[162]:= x=1 
During evaluation of In[162]:= x=2  
During evaluation of In[162]:= x=3 
Out[162]= True 

內置Or是短路也是值得的。 (但我意識到建立未計算的條款如與Table是一種痛苦):

In[173]:= Or[Print[1];True, Print[2];False] 
During evaluation of In[173]:= 1 
Out[173]= True 
+0

燁,工程perfe ct – 2010-11-15 07:31:31

+1

遲到了,我只想指出參數模式中的過多細節通常不適合Hold特性。例如,以下調用失敗:AnyTrue [i <10,{i,Range [5]}],原則上它不應該(模式不匹配,因爲在模式匹配時它不知道Range [ 5]是List)。這個稍微更一般的簽名將會消除這個問題:AnyTrue [expr_,{var_Symbol,lis_}]。此外,AnyTrue不能在M8的打包列表中工作 - 長度似乎存在一個錯誤:LengthWhile [Range [5],! TrueQ [#<10]&]給出5,我要報告它。 – 2011-01-13 02:15:37

+0

是的,好點的獅子座。在評估它之後,有一個更一般的模式並驗證論點會更好。 'HoldAll'而不是'HoldFirst'是必要的,因爲我們希望除'expr'之外還保留'var',否則就不會有更挑剔的模式出現問題。 – 2011-01-13 02:22:51

4

這不符合你的天賦,但我經常使用下面的效用函數,這類似於你心裏有什麼(他們使用純函數,而不是與指定變量表達式),也做短路:

some[f_, l_List] := True ===    (* Whether f applied to some  *) 
    Scan[If[f[#], Return[True]]&, l];   (* element of list is True.  *) 

every[f_, l_List] := Null ===    (* Similarly, And @@ f/@l   *) 
    Scan[If[!f[#], Return[False]]&, l];  (* (but with lazy evaluation). *) 

例如,邁克爾·派拉特的例子就是成爲這個:

In[1]:= some[(Print["x=", #]; # == 3)&, {1, 2, 3, 4, 5}] 

    During evaluation of In[1]:= x=1 
    During evaluation of In[1]:= x=2  
    During evaluation of In[1]:= x=3 
Out[1]= True 
+1

有用的技巧。請注意,使用「If」而不是「TrueQ」需要更多注意句法,即'every [False,{a,{1,3,5}}]'給出「True」 – 2010-11-18 09:15:59

+0

你讓我擔心起初,但我認爲這裏沒有錯誤。請注意,第一個參數需要是一個函數。 「每一個[False&,{1,3,5}]'都按預期工作。 – dreeves 2010-11-18 09:31:18

+0

正確,沒有錯誤,只是一種微妙的語義差異,因爲如果f對列表中的每個元素都評估爲「False以外的東西」,它就是「真」 – 2010-11-18 09:43:33