Re: Select from list
- To: mathgroup at smc.vnet.net
- Subject: [mg87777] Re: Select from list
- From: thomas <thomas.muench at gmail.com>
- Date: Wed, 16 Apr 2008 22:32:08 -0400 (EDT)
- References: <fu4fjb$nhp$1@smc.vnet.net>
On Apr 16, 11:06 am, Steve Gray <stev... at roadrunner.com> wrote: > I have a list like this: > > ptX= > {{1, 2, 3, 4}, {1, 2, 3, 5}, {1, 2, 4, 5}, {1, 3, 4, 5}, {2, 3, 4, 5}} > > and I want a list pointing to all the sublists above that contain both > a 2 and a 3. In this example I would get {1,2,5}. The best solution I > have, with more generality, is: > > va = 2; > vb = 3; > za = Map[Cases[#1, va]&, ptX] /. {} -> {0} > zb = Map[Cases[#1, vb]&, ptX] /. {} -> {0} > Flatten[Position[za*zb, {va*vb}]] > > which gives > > {{2}, {2}, {2}, {0}, {2}} > {{3}, {3}, {0}, {3}, {3}} > {1, 2, 5}. > > (This doesn't work if va or vb is zero. That's ok.) > There's probably a better way. Anyone? Thank you. > > Steve Gray Hi Steve, This approach is using a trick from Carl Woll to get non-zero positions in a list: NonzeroPositions[data_] := SparseArray[data] /. SparseArray[_, _, _, x_] :> Flatten[x[[2, 2]]] With that: findTwo[ptX_,va_,vb_]:= NonzeroPositions[Total[-Unitize[ptX - va] + 1, {2}]*Total[-Unitize[ptX - vb] + 1, {2}]] Here, -Unitize[ptX - va] + 1 replaces each occurance of va with 1, others are 0. Total[...,{2}] then adds up the values (i.e. you get 0 if va is not there) With list = Table[RandomSample[Range[9], 4], {10^6}]; We get In[10]:= Timing[findTwo[list, 2, 3] ;][[1]] Out[10]= 0.641 and some other approaches: In[11]:= Timing[ Flatten[Position[(Map[Cases[#1, 2] &, list] /. {} -> {0})*(Map[ Cases[#1, 3] &, list] /. {} -> {0}), {2*3}]];][[1]] Out[11]= 12.063