Modifica ogni elemento a seconda degli elementi precedenti

Oct 22 2020

Sto cercando di vedere se c'è una soluzione più idiomatica / concisa / pulita di quella che ho per questo.

Ho un elenco di scatole con altezze e voglio impilarle; cioè, aggiungi a ciascuna casella la distanza dal suo centro dall'origine. Vedi sotto:

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

La mia soluzione è questa:

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}}

Quindi sto ottenendo un elenco dei bordi e un elenco dei centri locali e li aggiungo.

C'è un modo diverso / migliore per modificare ogni elemento in un elenco, a seconda degli elementi precedenti? Apprezzerei particolarmente una stenografia perMapThread[Append[...

Soluzione

La combinazione delle prime due risposte ci dà

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}
L = Flatten/@Thread@{L,Y}

dove \[Transpose]è entrato con :tr:, che mi piace molto.

Risposte

4 kglr Oct 22 2020 at 21:49
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}}

O

MapThread[Append] @ {L, Y}
 {{h -> 1, y -> 1/2}, {h -> 2, y -> 2}}

O

Flatten /@ Thread @ {L, Y}
 {{h -> 1, y -> 1/2}, {h -> 2, y -> 2}}
2 ChrisDegnen Oct 22 2020 at 21:57
Clear[h, y]
a = {1, 2};
b = Accumulate[a] - a/2;
Transpose[{Thread[h -> a], Thread[y -> b]}]

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