6
$\begingroup$

I have pairs of numbers {a1, b1}, {a2, b2}, {a3, b3}, ..., {aN, bN}

What is the shortest way to compute and plot {a1, b1}, {a2, b1+b2}, {a3, b1+b2+b3},....?

$\endgroup$
2
  • 4
    $\begingroup$ {as, bs} = Transpose[pairs]; result = Transpose[{as, Accumulate[bs]}] $\endgroup$
    – user484
    Commented Nov 14, 2015 at 5:08
  • 2
    $\begingroup$ Or, Transpose[MapAt[Accumulate, Transpose[pairs], 2]]. $\endgroup$ Commented Nov 14, 2015 at 7:20

7 Answers 7

14
$\begingroup$
Accumulate@Array[b, {3}]
(* {b[1], b[1] + b[2], b[1] + b[2] + b[3]} *)

therefore:

{a, b} = Transpose[list];
Transpose[{a, Accumulate[b]}]

Also this will do the job:

Rest@FoldList[{#2[[1]], #1[[2]] + #2[[2]]} &, {0, 0}, list]

or even easier

list[[All,2]]=Accumulate@list[[All,2]]; list
$\endgroup$
11
$\begingroup$
FoldList[{0, 1} # + #2 &, list]
$\endgroup$
6
$\begingroup$

thanks to Mike Honeychurch, without pure function:

list = {{a1, b1}, {a2, b2}, {a3, b3}};
Thread[{Thread[list][[1]], Rest@FoldList[Plus, 0, Thread[list][[2]]]}]
(* {{a1, b1}, {a2, b1 + b2}, {a3, b1 + b2 + b3}} *)

and shorter (one expression):

Thread[{list[[All, 1]], Accumulate[list][[All, 2]]}]
$\endgroup$
2
  • $\begingroup$ Could you please explain a little bit more how Rest@FoldList structure works? $\endgroup$
    – Mary
    Commented Nov 14, 2015 at 17:30
  • 1
    $\begingroup$ @Maria. Rest just removes first element in the list, i.e. Rest[{1, 2, 3}] gives {2, 3}. @ is a shorthand for head application. So Rest@FoldList[...] is the same as Rest[FoldList[...]]. Finally, FoldList[Plus, 0, {a, b, c}] gives {0, a, a + b, a + b + c}. Now you may see why we need Rest - just to get rid of 0. $\endgroup$
    – garej
    Commented Nov 14, 2015 at 17:55
3
$\begingroup$

This is another way and an active effort to advertise the ThroughOperator that was developed by @Sjoerd Smit.

To the extend of my knowledge it was first suggested in this answer.

list = {{a1, b1}, {a2, b2}, {a3, b3}};
list[[All, 1]]
ResourceFunction["ThroughOperator"][{Accumulate}][
  list[[All, 2]]] // Flatten
Thread[{%%, %}]

{{a1, b1}, {a2, b1 + b2}, {a3, b1 + b2 + b3}}

$\endgroup$
2
  • 2
    $\begingroup$ (+1) ThroughOperator is very flexible, so I hope they consider it as an option in a future version. Nicely done, mate! :-) $\endgroup$ Commented Dec 31, 2023 at 1:21
  • 2
    $\begingroup$ @E.Chan-López thanks a lot! Indeed it is very flexible and bypasses some issues that non-resource functions have. Hopefully, they will consider, but who knows? $\endgroup$
    – bmf
    Commented Dec 31, 2023 at 2:39
3
$\begingroup$

Another implementation using FoldList and MapAt:

pairs = {{a1, b1}, {a2, b2}, {a3, b3}};

f = FoldList[Apply[Plus]@*Flatten@*List, Nothing, #] &;

By entering Nothing instead of zero as the initial element in FoldList, we avoid the need to use Rest to remove the first element of the cumulative list. This choice makes the code cleaner and avoids the need to handle special cases.

Transpose@MapAt[f, Transpose@pairs, 2]

(*{{a1, b1}, {a2, b1 + b2}, {a3, b1 + b2 + b3}}*)

As the version proposed by @J. M.'s eventual burnout in a comment, but without using Accumulate.

$\endgroup$
1
$\begingroup$
list = {{a1, b1}, {a2, b2}, {a3, b3}};

Using SubsetMap (new in 12.0)

SubsetMap[Accumulate, list, {All, 2}]

{{a1, b1}, {a2, b1 + b2}, {a3, b1 + b2 + b3}}

$\endgroup$
1
$\begingroup$
list = {{a1, b1}, {a2, b2}, {a3, b3}};

Using ReplaceAt (new in 13.1)

Transpose @ ReplaceAt[Transpose[list], x_ :> Accumulate[x], 2]

{{a1, b1}, {a2, b1 + b2}, {a3, b1 + b2 + b3}}

$\endgroup$

Your Answer

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

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