MathGroup Archive 1999

[Date Index] [Thread Index] [Author Index]

Search the Archive

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


  • Prev by Date: Re: Early out with Map?
  • Next by Date: Re: Re: Strange result of Limit function in Mathematica3.0
  • Previous by thread: Re: Early out with Map?
  • Next by thread: Re: Early out with Map?