Re: Creating sub-list based on a given criterion
- To: mathgroup at smc.vnet.net
- Subject: [mg110600] Re: Creating sub-list based on a given criterion
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Sun, 27 Jun 2010 04:56:40 -0400 (EDT)
Hi Dimitris, here is a solution based on repeated application of rules: In[1] :== Module[{temp, left}, Flatten[ds, 1] //. {{done___temp, Shortest[x__List] /; Total[{x}[[All, 2]]] >== 25, y___} :> {done, temp[x], y}, {done___temp, rest : {_, _, _} ..} :> {done, left[rest]}} /. temp | left -> List] Out[1]== {{{0, 0, 1}, {1, 0, -1}, {2, 0, -1}, {3, 0, -1}, {4, 0, -1}, {5, 588, -1}}, {{6, 2345, 1}}, {{7, 2418, 1}}, {{8, 2323, 1}}, {{9, 2179, 1}}, {{480, 23, 1}, {487, 23, 1}}, {{470, 29, 1}}, {{478, 32, 1}}, {{468, 25, 1}}, {{498, 19, -1}, {494, 15, 1}}, {{496, 20, 1}, {455, 33, 1}}, {{462, 27, 1}}, {{781, 1, 1}, {779, 1, 1}, {784, 0, 1}, {778, 0, 1}, {766, 1, -1}, {735, 1, -1}, {758, 1, -1}, {733, 2, -1}, {716, 0, -1}, {794, 1, 1}}} Note that the last list may not satisfy your criteria and in general simply gathers leftovers. You can convert it to a function as follows: Clear[rebin]; rebin[binned : {{{_?NumericQ, _?NumericQ, _?NumericQ} ..} ..}, minValue_?NumericQ] :== Module[{temp,left}, Flatten[binned, 1] //. {{done___temp, Shortest[x__List] /; Total[{x}[[All, 2]]] >== minValue, y___} :> {done, temp[x], y}, {done___temp, rest : {_, _, _} ..} :> {done, left[rest]}} /. temp|left -> List]; Then you just call, rebin[ds, 25] Generally, this kind of problems seem to be harder to solve in a very succinct manner in Mathematica without resorting to side effects, since in splitting the list some non-trivial run-time information is required. For example, you can solve the problem much easier if you allow side effects to be used: In[4]:== Module[{sum == 0}, Split[Flatten[ds, 1], (sum +== #1[[2]]; If[sum >== 25, sum == 0; False, True]) &]] Out[4]== {{{0, 0, 1}, {1, 0, -1}, {2, 0, -1}, {3, 0, -1}, {4, 0, -1}, {5, 588, -1}}, {{6, 2345, 1}}, {{7, 2418, 1}}, {{8, 2323, 1}}, {{9, 2179, 1}}, {{480, 23, 1}, {487, 23, 1}}, {{470, 29, 1}}, {{478, 32, 1}}, {{468, 25, 1}}, {{498, 19, -1}, {494, 15, 1}}, {{496, 20, 1}, {455, 33, 1}}, {{462, 27, 1}}, {{781, 1, 1}, {779, 1, 1}, {784, 0, 1}, {778, 0, 1}, {766, 1, -1}, {735, 1, -1}, {758, 1, -1}, {733, 2, -1}, {716, 0, -1}, {794, 1, 1}}} Hope this helps. Regards, Leonid On Sat, Jun 26, 2010 at 12:10 AM, Dimitris Emmanoulopoulos < demmanoulopoulos at hotmail.com> wrote: > Hello > > I was wondering if there is any straightforward way to bin a list into > sub-lists containing those elements that full-fill a given criterion. > Consider the following list > > ds== > > {{{0,0,1},{1,0,-1},{2,0,-1},{3,0,-1},{4,0,-1},{5,588,-1},{6,2345,1},{7,24= 18,1},{8,2323,1},{9,2179,1}},{{480,23,1},{487,23,1},{470,29,1},{478,32,1},{= 468,25,1},{498,19,-1},{494,15,1},{496,20,1},{455,33,1},{462,27,1}},{{781,1,= 1},{779,1,1},{784,0,1},{778,0,1},{766,1,-1},{735,1,-1},{758,1,-1},{733,2,-1= },{716,0,-1},{794,1,1}}} > > The criterion is that the sum of the second elements in each new sub-list > should be at least 25? > > After the re-binning we should get something like: > > {{0,0,1},{1,0,-1},{2,0,-1},{3,0,-1},{4,0,-1},{5,588,-1}} > {6,2345,1} > {7,2418,1} > {8,2323,1} > {9,2179,1} > {{480,23,1},{487,23,1}} > {470,29,1} > {478,32,1} > {468,25,1}, > {498,19,-1},{494,15,1}, > {496,20,1},{455,33,1} > > {{462,27,1},{781,1,1},{779,1,1},{784,0,1},{778,0,1},{766,1,-1},{735,1,-1}= ,{758,1,-1},{733,2,-1},{716,0,-1},{794,1,1}}} > > The first bin has a total of the second elements 588, the second 2345, th= e > third 2418,...,the sixth 46, the seventh 29, =85,the eleventh 53, and the= last > one 35. > > In other words, imagine that these are the results of a counting experime= nt > and the second element in every entry (in ds) corresponds to counts. The > question is how can we re-bin the data in order to have at least 25 count= s > per new-bin? > Of course it is straightforward to do it using a Do-loop, but I was > wondering if there is any simpler way to do it using the efficient > Mathematica syntax in an =93one-liner expression=94. > > Thanks a lot > Dimitris > >