# Modify each element depending on previous elements

I'm looking to see if there's a more idiomatic/concise/neat solution than what I have for this.

I have a list of boxes with heights and I want to stack them; that is, add to each box the distance to its center from the origin. See below:

  |->|-----| -|   |
h1|  |  .  |<-|y1 |
|->|_____|      |
|->|-----|      |
|  |     |      |
h2|  |  .  |<-----|y2
|  |     |
|->|_____|


My solution is this:

L = {
{h -> 1},
{h -> 2}
};
(* measure distances *)
Y = y -> # & /@ ((h/2 /. L) + Most@Accumulate[h /. {{h -> 0}}~Join~L]);
(* append distances to elements *)
L = MapThread[Append[#1, #2] &, {L, Y}]

Out= {
{h -> 1, y -> 1/2},
{h -> 2, y -> 2}}


So I'm getting a list of the edges and a list of the local centers and adding those.

Is there a different/better way to modify each element in a list, depending on previous elements? I would especially appreciate a shorthand for MapThread[Append[...

Solution

Combining the first two responses gives us

L = {{h -> 1}, {h -> 2}};
Y = Thread[y -> Accumulate[h /. L] - (h/2 /. L)]
(* one of: *)
L = {L, Y}\[Transpose] // Map@Flatten
L = Flatten/@Transpose@{L,Y}


where \[Transpose] is entered with :tr:, which I like a lot.

L = {{h -> 1}, {h -> 2}};

Y = Thread[y -> Flatten[Accumulate[Values@L ] - Values@L/2]];

Join[L, List /@ Y, 2]

 {{h -> 1, y -> 1/2}, {h -> 2, y -> 2}}


Or

MapThread[Append] @ {L, Y}

 {{h -> 1, y -> 1/2}, {h -> 2, y -> 2}}


Or

Flatten /@ Thread @ {L, Y}

 {{h -> 1, y -> 1/2}, {h -> 2, y -> 2}}

• Much better usage of Thread! Changing the + to -, I don't know how I missed that thanks. I like the currying in your second example too. Commented Oct 23, 2020 at 2:03
Clear[h, y]
a = {1, 2};
b = Accumulate[a] - a/2;