RE: Early out with Map?
- To: mathgroup at smc.vnet.net
- Subject: [mg16044] RE: [mg16036] Early out with Map?
- From: "Ersek, Ted R" <ErsekTR at navair.navy.mil>
- Date: Sun, 21 Feb 1999 00:15:19 -0500
- Sender: owner-wri-mathgroup at wolfram.com
Oscar Stiffelman wrote:
__________________________
Is it possible to interrupt Map before it reaches then end of the list?
For example, how would I convert the following from procedural to
functional?
(* This is the procedural version *)
foundSolution = False;
For[i =1, i <= numChildren && ! foundSolution, i++,
If[testChild[children[[i]]],
foundSolution = True;
];
];
foundSolution
____________________
This is a great place to use Throw and Catch (a complementary pair that took
a long time for me to grasp). You didn't indicate what you are using for
children, numChildren, and testChild. I will use the definitions below.
In[1]:=
children={2,3,-4,3,7,-2,4,-5,1,3,-6,1};
numChildren=Length[children];
testChild[a_]:=a<0
____________________
Then your procedural version returns True since children contains negative
numbers.
In[4]:=
(* This is the procedural version *)
foundSolution = False;
For[i =1, i <= numChildren && ! foundSolution, i++,
If[testChild[children[[i]]],
foundSolution = True;
];
];
foundSolution
Out[7]=
True
____________________
Below I show how Throw and Catch can be used to make Map quit early.
In[8]:=
children1={2,3,4,3,7,2,4,5,1,3,6,1};
children2={2,3,-4,3,7,-2,4,-5,1,3,-6,1};
In[10]:=
Catch[
Map[If[Negative[#],Throw[True]]&,children1];
False
]
Out[10]=
False
In[11]:=
Catch[
Map[If[Negative[#],Throw[True]]&,children2];
False
]
Out[11]=
True
____________________
But I think simplest solution uses Select.
In[12]:=
?Select
"Select[list, crit] picks out all elements ei of list for which crit[ei] is
True. Select[list, crit, n] picks out the first n elements for which
crit[ei] is True."
In[13]:=
Select[children1,Negative,1]
Out[13]=
{}
In[14]:=
Select[children2,Negative,1]
Out[14]=
{-4}
But you don't want the one that passed the test. You want True or False, so
I compare the result to {} in the next line.
In[15]:=
Select[children2,Negative,1]=!={}
Out[15]=
True
______________________
Look-up Cases in the Help Browser and you will see
Cases[expr, pattern, levspec, n] gives the first (n) parts in expr which
match the pattern. If anyone wants a discussion of 'levelspec' let me know.
In the lines below I do the same with Cases.
In[16]:=
Cases[children1,_?Negative,1,1]
Out[16]=
{}
In[17]:=
Cases[children2,_?Negative,1,1]
Out[17]=
{-4}
In[18]:=
Cases[children2,_?Negative,1,1]=!={}
Out[18]=
True
_______________________
Cases is a very powerful feature because:
- Pattern matching is VERY versatile.
- 'pattern' can be (pattern->expr)
or (pattern:>expr).
- Levelspec gives a wealth of possibilities.
- As with all functional programming in Mathematica
Cases works with any expression (not only lists).
_____________________
But as I recently warned, be wary of (pattern->expr).
If (pattern) has a name (e.g. n_?Negative) and the pattern name is used in
(expr) then you get the wrong result if (n) has a global value.
Instead use (pattern:>name).
______________________
Regards,
Ted Ersek