Re: selecting from lists
- To: mathgroup at smc.vnet.net
 - Subject: [mg6137] Re: [mg6120] selecting from lists
 - From: support (Tom Zeller)
 - Date: Sun, 23 Feb 1997 00:10:50 -0500
 - Sender: owner-wri-mathgroup at wolfram.com
 
>The problem: given an arbitrary list v and a list b of the same
>length, whose entries are all Boolean (True or False), construct a
>function s[v, b] whose result is a list consisting only of those
>entries of v for which the corresponding entries in b are True.  For
>example,
>
>   v = {3, 82, 7, -12, 5};
>   b = {False, True, True, False};
>   s[v, b]
>{82, 7}
>
>Of course, a looping solution is obvious.  But I want something that
>works on the entire list at once (as in the APL or J programming
>languages, where this sort of thing is utterly trivial).  The best
>I've come up with so far is the following:
>
>   bpick[x_, b_] := If[b, {x}, {}]
>   SetAttributes[bpick, Listable]
>   s[v_, b_] := Flatten[bpick[v, b]]
>
>Is there some nicer, more direct way?  No Table's, Do's, or For's,
>please!
>
Like the passengers of the Titanic, I will attend to the tip of the iceberg
only ......
Here is a combination of Mathematica list handling functions and a pure
function that will do what you ask above.
In[16]:=
   v = {3, 82, 7, -12, 5};
   b = {False, True, True, False, True};
(* list b was added to to make the lists the same length *)
Here it is in steps:
In[21]:=
pairs=Transpose[{v, b}]
Out[21]=
{{3, False}, {82, True}, {7, True}, {-12, False}, {5, True}}
In[22]:=
Select[pairs, #[[2]]&]
Out[22]=
{{82, True}, {7, True}, {5, True}}
In[23]:=
Map[First, %]
Out[23]=
{82, 7, 5}
Here are the steps rolled into a function.
In[24]:=
f[x_List, y_List] := Map[First, Select[Transpose[{x,y}], #[[2]]&]]
In[25]:=
f[v, b]
Out[25]=
{82, 7, 5}
Tom Zeller
Wait! what is that under the water?!
>Actually, the general problem as I formulated it above is just the tip
>of the iceberg of things that are giving me trouble in Mathematica
>that are so easy for me in APL or J.  For example, construct a
>function firstnonzero that returns the index of the first nonzero
>entry in a list (or, more generally, the first entry in a list
>satisfying a given property).  Here the best I've come up with that
>avoids explicit looping is:
>
>   nonzero[x_] != 0; SetAttributes[nonzero, Listable]
>   firstnonzero[v_] := First[s[Range[Length[v]], nonzero[v]]]
>
>In these and similar problems, I have the feeling that there ought to
>be some slick approach using patterns, but I don't see how to do it.
>
>Any help in putting me onto the right track in "Mathematica thinking"
>about such problems would be appreciated.
>
>--
>  Murray Eisenberg                       Internet:  murray at math.umass.edu
>  Mathematics & Statistics Dept.            Voice:  413-545-2859 (W)
>  University of Massachusetts                       413-549-1020 (H)
>  Amherst, MA 01003                           Fax:  413-545-1801