Re: Operating on every k-th element of list?
- To: mathgroup at smc.vnet.net
- Subject: [mg37100] Re: [mg37080] Operating on every k-th element of list?
- From: Andrzej Kozlowski <andrzej at tuins.ac.jp>
- Date: Wed, 9 Oct 2002 05:25:57 -0400 (EDT)
- Sender: owner-wri-mathgroup at wolfram.com
Let's first consider your original problem and take a small list as an example: mylist = {a, b, c, d, e, f, g}; As you pointed out there is a rather obvious and natural way to do it using the Do loop. In[5]:= Do[mylist[[3*i + 1]] = k*mylist[[3*i]] + mylist[[3*i + 1]], {i, 1, Length[mylist]/3}]; mylist Out[5]= {a, b, c, d + c*k, e, f, g + f*k} One can also do it using something like your second approach. Notice the need to re-set mylist which got changed by the Do loop: In[6]:= mylist={a,b,c,d,e,f,g}; In[7]:= RotateRight[Table[If[Mod[i,3]==0,k, 0],{i,1,Length[mylist]}]*mylist]+mylist Out[7]= {a,b,c,d+c k,e,f,g+f k} There is an ambiguity that appears if the length of the list is exactly divisible by 3. In that case k times the last element should be added to the next element. In this case the first approach (using Do) will produce an error message while the second will interpret "the next element" to mean the first element of the list. One can fix that but I shan't bother to do so and assume that the length of the list is not divisible by 3. Now let's take a large list and compare the performance of the two approaches: In[8]:= k = 2; In[9]:= mylist = Table[Random[Integer, {1, 9}], {10000}]; In[11]:= mylist1 = mylist; In[12]:= Timing[list1 = (Do[mylist[[3*i + 1]] = k*mylist[[3*i]] + mylist[[3*i + 1]], {i, 1, Length[mylist]/3}]; mylist); ] Out[12]= {0.21999999999999997*Second, Null} In[13]:= mylist = mylist1; In[14]:= Timing[list2 = RotateRight[Table[If[Mod[i, 3] == 0, k, 0], {i, 1, Length[mylist]}]*mylist] + mylist; ] Out[14]= {0.020000000000000018*Second, Null} In[15]:= list1 == list2 Out[15]= True So you were right, at least in this implementation the second approach turns out to be much faster. Note also however, that when you change the problem to the one that you originally stated the two approaches will no longer give the same answer. The reason is that your statement is ambiguous: "apply a function to every k-th element of a long list and add the result to the k+1 element" can either mean that you want to take the original k-th element of the original list, multiply by a constant and add to the next one, or do the same with the already altered k-th element (by the previous step of the procedure). The Do loop approach will do the latter and the other the former. Andrzej Kozlowski Yokohama, Japan http://www.mimuw.edu.pl/~akoz/ http://platon.c.u-tokyo.ac.jp/andrzej/ On Tuesday, October 8, 2002, at 08:17 PM, AES wrote: > I want to apply a function to every k-th element of a long list and > add the result to the k+1 element. > > [Actually k = 3 and I just want to multiply myList[[k]] by a > constant (independent of k) and add the result to myList[[k+1]] for > every value of k that's divisible by 3.] > > Is there a way to do this -- or in general to get at every k-th > element of a list -- that's faster and more elegant than writing a > brute > force Do[] loop or using Mod[] operators, and that will take > advantage of native List operators, but still not be too recondite? > > I've been thinking about multiplying a copy of myList by a "mask > list" > {0,0,1,0,0,1,..} to generate a "masked copy" and approaches like that. > Better ways??? > > >