Re: There must be a better way!

*To*: mathgroup at smc.vnet.net*Subject*: [mg2341] Re: There must be a better way!*From*: wagner at goober.cs.colorado.edu (Dave Wagner)*Date*: Wed, 25 Oct 1995 02:13:14 -0400*Organization*: University of Colorado, Boulder

In article <DGxuMB.G69 at wri.com>, <pehowland at taz.dra.hmg.gb> wrote: > >Hi. I'm trying to write a function that partitions a list into >segments of length given by another length. eg. > Given l1 = {A,B,C,D,E,F,G,H,I,J} > and l2 = {2,3,4,1} >I want to be able to say > In[1] := MyPartition[l1, l2] >and get > Out[1] = {{A,B}, {C,D,E}, {F,G,H,I}, {J}} In the following, I'm using "list1" and "list2" in place of "l1" and "l2", which look too much like the integers 11 and 12 to me! (I couldn't for the life of me figuring out why you were calling MyPartition[11, 12]!!!) The key idea in the following solution is that you can use the syntax Take[list, {x, y}] to take the x-th throught y-th element from a list in a single operation. If we could somehow turn {2,3,4,1} into {{1,2}, {3,5}, {6,9}, {10,10}}, then we could simply map Take[list1, #]& onto that list. Here goes: In[1]:= list1 = {a,b,c,d,e,f,g,h,i,j}; list2 = {2,3,4,1}; First compute cumulative partial sums of list2: In[3]:= FoldList[Plus, First[list2], Rest[list2]] Out[3]= {2, 5, 9, 10} The result is a list of the second elements of the list we're trying to construct. Obviously, after we construct the first elements, there's a Transpose waiting to happen. Here are the first elements: In[4]:= RotateRight[Mod[%,10]+1, 1] Out[4]= {1, 3, 6, 10} (You would want to use Length[list1] in place of 10 in a production version of this code.) In[5]:= Transpose[{%, %%}] Out[5]= {{1, 2}, {3, 5}, {6, 9}, {10, 10}} There you have it: In[6]:= Take[list1, #]& /@ % Out[6]= {{a, b}, {c, d, e}, {f, g, h, i}, {j}} Dave Wagner Principia Consulting (303) 786-8371 dbwagner at princon.com http://www.princon.com/princon