Re: More Efficient Method

*To*: mathgroup at smc.vnet.net*Subject*: [mg105216] Re: More Efficient Method*From*: Ray Koopman <koopman at sfu.ca>*Date*: Tue, 24 Nov 2009 05:51:33 -0500 (EST)*References*: <he5v47$3am$1@smc.vnet.net>

On Nov 20, 3:38 am, blamm64 <blam... at charter.net> wrote: On Nov 20, 3:38 am, blamm64 <blam... at charter.net> wrote: > I have a couple of functions designed to poke a single hole, and to > poke multiple holes, in a one-level list: > > We define a function which, given the imported pressure data, finds > the subset of that pressure data excluding the pressure data points > between "targetL " and "targetU". > > In[5]:= findsubset[data_?VectorQ,targetL_?NumericQ,targetU_? > NumericQ] := Select[data,(#<=targetL || #>=targetU &)] > > This function will pluck out multiple holes in the data list. > > In[6]:= subsets[data_?VectorQ,tarList_?ListQ]:=Module[{tmp,tmp1}, > tmp=data; > Do[tmp1=findsubset[tmp,tarList[[i,1]],tarList[[i,2]]];tmp=tmp1, > {i,Dimensions[tarList][[1]]}]; > tmp > ] > > The following works fine (big holes chosen not to give large result): > > In[7]:= datalist=Range[11,3411,10]; > > In[12]:= targetlist={{40, 1500},{1600,3300}}; > > In[13]:= resultdata=subsets[datalist,targetlist] > > Out[13]= > {11,21,31,1501,1511,1521,1531,1541,1551,1561,1571,1581,1591, > 3301,3311,3321,3331,3341,3351,3361,3371,3381,3391,3401,3411} > > But if "datalist" happens to be very large, surely there is a (much) > more efficient method? > > I tried unsuccessfully to use pure functions with Select, but have a > somewhat nebulous feeling there's a pure function way of doing this > effectively much more efficiently. > > I know, I know: the above have no consistency checking. I also know > "subsets" could be used in place of "findsubset" just by replacing > the call of "findsubset" with the code of "findsubset" in "subsets". > > From what I've seen on this forum there are some really experienced > people who might provide an efficient way of implementing the above. > > -Brian L. In your example, 'datalist' contains sorted integers, and 'targetlist' contains sorted nonoverlapping "holes" with integer bounds. If this will always be the case then the following code, that "walks" the two lists together, will be much faster than using IntervalMemberQ. funk = Compile[{{datalist,_Integer,1},{targetlist,_Integer,2}}, Module[{b = Append[Flatten[{0,-1}+#&/@targetlist],Last@datalist+1], j = 1}, Select[datalist,(While[b[[j]]<#,j++]; OddQ@j)&]]]