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