Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"short circuiting" And and Or

5 views
Skip to first unread message

Szabolcs Horvat

unread,
Oct 20, 2006, 5:36:39 AM10/20/06
to
I'd like to write a function that tests whether there are any elements
in a list that violate a certain condition. I could simply use
And@@condition/@list, but for reasons of efficiency I'd like to stop
the testing as soon as a "False" value is found. Is there any elegant
way of doing this without writing an explicit While loop?

Szabolcs Horvát

Jean-Marc Gulliet

unread,
Oct 21, 2006, 5:16:15 AM10/21/06
to
Say we have some lists of integers and we want to check that the lists
contain only positive integers less or equal to ten. We can use the
built-in function Select with the logical tests written as an anonymous
function. Also, we set the last parameter of Select to one in order to
stop searching the list at the first occurrence where the conditions do
not hold. If the list returned by Select is empty, we conclude that the
conditions hold for every elements of the original list.

In[1]:=
list1={5,2,-3,0,2,7,10,3,3,2,3,6,10,8,8,7,9,4,8,3};
list2={5,2,3,1,2,7,10,3,3,2,3,6,10,8,8,7,9,4,8,3};
violateConditionsQ[data_List,cond_]:=
If[Length[Select[data,cond,1]]>0,True,False]

In[4]:=
violateConditionsQ[list1,(#<=0||#>10)&]

Out[4]=
True

In[5]:=
violateConditionsQ[list2,(#<=0||#>10)&]

Out[5]=
False

Regards,
Jean-Marc

Carl Woll

unread,
Oct 21, 2006, 5:22:41 AM10/21/06
to
Szabolcs Horvat wrote:

>I'd like to write a function that tests whether there are any elements
>in a list that violate a certain condition. I could simply use
>And@@condition/@list, but for reasons of efficiency I'd like to stop
>the testing as soon as a "False" value is found. Is there any elegant
>way of doing this without writing an explicit While loop?
>
>Szabolcs Horvát
>

Here is one idea:

ReleaseHold[
And @@ (Hold[Positive[#]]& /@ {1,1,-1,1,-1,1})
]

False

Here is one way to check that testing is stopped as soon as a False
value is found:

ReleaseHold[
And @@ (Hold[Print[#];Positive[#]]& /@ {1,1,-1,1,-1,-1,1})
]

1
1
-1
False

Carl Woll
Wolfram Research

Sseziwa Mukasa

unread,
Oct 21, 2006, 5:29:48 AM10/21/06
to

On Oct 20, 2006, at 5:21 AM, Szabolcs Horvat wrote:

> I'd like to write a function that tests whether there are any elements
> in a list that violate a certain condition. I could simply use
> And@@condition/@list, but for reasons of efficiency I'd like to stop
> the testing as soon as a "False" value is found. Is there any elegant
> way of doing this without writing an explicit While loop?

Elegance is in the eye of the beholder but

NestWhile[Block[{l =
Rest[#]}, If[l == {}, l, Prepend[Rest[l],
And[First[#], condition[First[
l]]]]]] &, Prepend[list, True], # != {} && First[#] &]

gives the desired result. It returns a list containing the first
element which for which condition is false followed by the rest of
the original list.

Regards,

Ssezi

János

unread,
Oct 21, 2006, 5:30:49 AM10/21/06
to

On Oct 20, 2006, at 5:21 AM, Szabolcs Horvat wrote:

> I'd like to write a function that tests whether there are any elements
> in a list that violate a certain condition. I could simply use
> And@@condition/@list, but for reasons of efficiency I'd like to stop
> the testing as soon as a "False" value is found. Is there any elegant
> way of doing this without writing an explicit While loop?
>

> Szabolcs Horvát

Here is a newbie approach:

In[1]:=
lst = {1, 2, 3, 4, 5, 6, 7,
8, 9.1, 10, 11, 12};

In[2]:=
f[x_] := If[x \[Element] Integers,
Null, Throw[x]];

In[3]:=
Catch[Scan[f, lst]]
Out[3]=
9.1

János


----------------------------------------------
Trying to argue with a politician is like lifting up the head of a
corpse.
(S. Lem: His Master Voice)

Carl Woll

unread,
Oct 21, 2006, 5:32:51 AM10/21/06
to
Szabolcs Horvat wrote:

>I'd like to write a function that tests whether there are any elements
>in a list that violate a certain condition. I could simply use
>And@@condition/@list, but for reasons of efficiency I'd like to stop
>the testing as soon as a "False" value is found. Is there any elegant
>way of doing this without writing an explicit While loop?
>
>Szabolcs Horvát
>
>

In addition to using ReleaseHold/Hold, another idea is possible if
And[list] doesn't evaluate. For example:

condition[x_]:=(Print[x]; Positive[x])

condition /@ And @@ {1,1,-1,1,1,-1,1}

dkr

unread,
Oct 21, 2006, 5:44:01 AM10/21/06
to
Use Cases with 4 arguments. For example,
In[2]:=
Cases[{a,b,c},x_/;x=!=a,{1},1]
Out[2]=
{b}


dkr

David Bailey

unread,
Oct 21, 2006, 5:47:03 AM10/21/06
to
Hello,

The following program illustrates that this is already the behaviour:

f1[]:=(Print["f1"];False);
f2[]:=(Print["f2"];False);

f1[] && f2[]

Notice that And has attribute HoldAll - so it can evaluate its arguments
as required, and that it does not have attribute Orderless - so the
arguments can't get permuted.

David Bailey
http://www.dbaileyconsultancy.co.uk

Jens-Peer Kuska

unread,
Oct 21, 2006, 5:55:15 AM10/21/06
to
Hi,

something like

Catch[
If[TrueQ[#], Throw[$Failed], Print[#]] & /@

{False, a, b, False, True, True,True}
]

Regards

Jens

"Szabolcs Horvat" <szho...@gmail.com> schrieb im
Newsbeitrag news:eha5b7$b5b$1...@smc.vnet.net...

Chris Chiasson

unread,
Oct 21, 2006, 5:58:17 AM10/21/06
to
condition /@ (And @@ list)

If the objects in your list will not react to being contained inside
an And, apply it first and then map the condition onto it.

Otherwise, use Catch, Scan, and Throw

On 10/20/06, Szabolcs Horvat <szho...@gmail.com> wrote:
> I'd like to write a function that tests whether there are any elements
> in a list that violate a certain condition. I could simply use
> And@@condition/@list, but for reasons of efficiency I'd like to stop
> the testing as soon as a "False" value is found. Is there any elegant
> way of doing this without writing an explicit While loop?
>
> Szabolcs Horvát
>
>


--
http://chris.chiasson.name/

Chris Chiasson

unread,
Oct 22, 2006, 2:09:17 AM10/22/06
to
I did not know about the HoldAll attribute of And. Thank you.

On 10/21/06, David Bailey <dave@remove_thisdbailey.co.uk> wrote:

> Hello,
>
> The following program illustrates that this is already the behaviour:
>
> f1[]:=(Print["f1"];False);
> f2[]:=(Print["f2"];False);
>
> f1[] && f2[]
>
> Notice that And has attribute HoldAll - so it can evaluate its arguments
> as required, and that it does not have attribute Orderless - so the
> arguments can't get permuted.
>
> David Bailey
> http://www.dbaileyconsultancy.co.uk
>
>
>
>
>
>


--
http://chris.chiasson.name/

0 new messages