5
$\begingroup$

New to Mathematica, I have a nested list containing many lists(A) of 16 lists(B) of 3 integers(C). I wish to put in each (Aj, Bi, C2) the result of (Aj, Bi-1, C2)+(Aj, Bi, C1). I could do it with a loop, or a spreadsheet, but is there a more elegant way to do this using functions like Accumulate? I simplified the data here:

 myList = 
    {{{a, b}, {c, d}, {e, f}}, 
    {{g, h}, {i, j}, {k, l}}, 
    {{m, n}, {o, p}, {q, r}}, 
    {{s, t}, {u, v}, {w, x}}}

A simple replacement test function before using values of other elements:

myF[x_] := x*2
ReplacePart[myList, {_, _, 2} -> xx]

Result:

{{{a, xx}, {c, xx}, {e, xx}}, 
{{g, xx}, {i, xx}, {k, xx}}, 
{{m, xx}, {o, xx}, {q, xx}},
{{s, xx}, {u, xx}, {w, xx}}}

I tried many expressions in the function without success.

ReplacePart[myList, {_, _, 2} -> myF[ ??? ]]

should result:

{{{a, 2b}, {c, 2d}, {e, 2f}}, 
{{g, 2h}, {i, 2j}, {k, 2l}}, 
{{m, 2n}, {o, 2p}, {q, 2r}}, 
{{s, 2t}, {u, 2v}, {w, 2x}}}

How could Accumulate give this?

{{{a, a}, {c, a+c}, {e, a+c+e}}, 
{{g, g}, {i, g+i}, {k, g+i+k}}, 
{{m, m}, {o, m+o}, {q, m+o+q}}, 
{{s, s}, {u, s+u}, {w, s+u+w}}}

Thanks!

$\endgroup$
2
  • $\begingroup$ The solutions are so concise and powerful! It's very exiting to discover in the same time Mathematica and Stackexchange. Thank you march, ubpdqn and eldo for your answers. $\endgroup$
    – makundo
    Dec 6, 2015 at 21:32
  • $\begingroup$ For the first one, after Mr Wizard here: myList.{{1, 0}, {0, 2}}. Very fast, I think. $\endgroup$
    – user1066
    Jul 12, 2016 at 18:06

3 Answers 3

5
$\begingroup$
myList = {
  {{a, b}, {c, d}, {e, f}}, 
  {{g, h}, {i, j}, {k, l}}, 
  {{m, n}, {o, p}, {q, r}}, 
  {{s, t}, {u, v}, {w, x}}
 };

For the first, one could do

MapAt[2 # &, myList, {All, All, 2}]
(* {
  {{a, 2*b}, {c, 2*d}, {e, 2*f}}, 
  {{g, 2*h}, {i, 2*j}, {k, 2*l}}, 
  {{m, 2*n}, {o, 2*p}, {q, 2*r}}, 
  {{s, 2*t}, {u, 2*v}, {w, 2*x}}
 } *)

or with your

myF[x_] := x*2

do

MapAt[myF, myList, {All, All, 2}]

As for the second, here's another version that is basically equivalent to ubpdqn's, but slightly less verbose:

Thread@{#, Accumulate@#} &@#[[All, 1]] & /@ myList

Or, a trickier variant:

Thread@{#, Accumulate@#} & @@@ Thread /@ myList

Here's a version that uses ReplaceAll, with a dummy variable to update so that we don't have to Accumulate:

Map[
  Module[{var = 0}, # /. {a_, b_} :> (var = var + a; {a, var})] &
  , myList
 ]

However, ReplaceAll with this pattern will fail when the sub-list is two elements long. Instead, we use Replace, and make the code more concise:

Module[{var = 0}, 
  Replace[#, {a_, b_} :> {a, var = var + a}, 2]
 ] & /@ myList
$\endgroup$
1
  • $\begingroup$ Completely new to me that one can combine MapAt with All. Very handy, +1 $\endgroup$
    – eldo
    Dec 6, 2015 at 21:12
6
$\begingroup$

I believe this achieves your goal:

Join @@ Map[Transpose[{#, Accumulate@#}] &, Transpose /@ myList, {2}]

Transpose is a very helpful function. This also exploits the level argument for Map and Join just recombines.

There are many ways to do things in Mathematica. There will no doubt other approaches.

$\endgroup$
1
  • 2
    $\begingroup$ This will be faster on packed arrays: Transpose[{#, Accumulate@#} &@First@Transpose[myList, {3, 2, 1}], {3, 2, 1}]. $\endgroup$
    – Michael E2
    Dec 6, 2015 at 21:10
5
$\begingroup$

ReplacePart is not the natural choice to apply a function to the innermost matrix elements. Simple and straightforward is ReplaceAll:

myList /. {a_, b_} :> {a, myF @ b} // MatrixForm

enter image description here

With very large matrices ReplaceAll can get slow. In this case one can do an "inline" replacement. Since this permanently changes myList we do it with a copy:

copy = myList;

copy[[All, All, 2]] *= 2;

Thanks @MichaelE2 for this terse notation

copy

enter image description here

Accumulate with

Transpose /@ Transpose[{#, Accumulate /@ #}] &[myList[[All, All, 1]]] // MatrixForm

enter image description here

$\endgroup$
2
  • 1
    $\begingroup$ I think copy[[All, All, 2]] *= 2 will be faster on longer, large packed arrays. (+1) $\endgroup$
    – Michael E2
    Dec 6, 2015 at 20:57
  • $\begingroup$ Of course, thanks for this valuable advice - will update :) $\endgroup$
    – eldo
    Dec 6, 2015 at 21:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.