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