Modifier chaque élément en fonction des éléments précédents

Oct 22 2020

Je cherche à voir s'il existe une solution plus idiomatique / concise / soignée que ce que j'ai pour cela.

J'ai une liste de boîtes avec des hauteurs et je veux les empiler; c'est-à-dire, ajoutez à chaque boîte la distance entre son centre et l'origine. Voir ci-dessous:

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

Ma solution est la suivante:

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

Je reçois donc une liste des bords et une liste des centres locaux et j'ajoute ceux-ci.

Existe-t-il une manière différente / meilleure de modifier chaque élément d'une liste, en fonction des éléments précédents? J'apprécierais particulièrement un raccourci pourMapThread[Append[...

Solution

La combinaison des deux premières réponses nous donne

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}

où \[Transpose]est entré avec :tr:, ce que j'aime beaucoup.

Réponses

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

Ou

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

Ou

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