Re: selecting from lists

*To*: mathgroup at smc.vnet.net*Subject*: [mg6139] Re: [mg6120] selecting from lists*From*: "w.meeussen" <w.meeussen at solair4b.eunet.be>*Date*: Sun, 23 Feb 1997 00:10:52 -0500*Sender*: owner-wri-mathgroup at wolfram.com

At 23:46 21-02-97 -0500, you wrote: >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! > >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 > > why not : In[7]:= Part[v,Flatten at Position[b,True]] Out[7]= {82,7} and In[19]:= li={a,Null,33,33.7,False,Pi,1+x+x^2,"anything",{1},f[x]}; In[20]:= Position[li,_Integer] Out[20]= {{3},{7,1},{7,3,2},{9,1}} In[26]:= Position[li,_Symbol,Heads->False] Out[26]= {{1},{2},{5},{6},{7,2},{7,3,1},{10,1}} the list element "1+x+x^2" is Plus[1,x,Power[x,2]] that's why the levels are nested. you might want to replace the pattern test by a pure-function test: In[28]:= Position[li,t_/;(Sqrt[t]>5)] Out[28]= {{3},{4}} meaning 'anything,(temporarily called t)with the condition that (the "/;") meets the condition Sqrt[t]>5. Of course, the function Sqrt could be a pure function too : Power[#,1/2]& or (1-#+#^2)& or whatever ... have fun, Dr. Wouter L. J. MEEUSSEN w.meeussen at solair4b.eunet.be