1

Is there a built in function or an easy rule to do the following transformation?

H[{A[0], A[1], ...},{B[0], B[1], ...},...]

into

{H[A[0], B[0]], H[A[1], B[1]], ...}
Lorenzo Pistone
  • 1,607
  • 11
  • 16

1 Answers1

1

Thread does this:

expr = h[{a[0], a[1], a[2]}, {b[0], b[1], b[2]}, {c[0], c[1], c[2]}];

Thread[expr]
{h[a[0], b[0], c[0]], h[a[1], b[1], c[1]], h[a[2], b[2], c[2]]}

If however your subexpressions are not the same length you will get an error:

expr2 = h[{a[0], a[1], a[2]}, {b[0], b[1]}, {c[0]}];

Thread[expr2]

Thread::tdlen: Objects of unequal length in h[{a[0],a[1],a[2]},{b[0],b[1]},{c[0]}] cannot be combined. >>

One could use Flatten to do something like this:

h @@@ Flatten[List @@ expr2, {2}]
{h[a[0], b[0], c[0]], h[a[1], b[1]], h[a[2]]}

To understand Flatten see: Flatten command: matrix as second argument.

There is a problem with the simple form above however. Note what happens if h is made to hold its arguments unevaluated, and a is given a definition which we do not wish to trigger:

Attributes[h] = {HoldAll};

a[_] = "Fail!";

Thread still works as desired:

Thread[expr]
{h[a[0], b[0], c[0]], h[a[1], b[1], c[1]], h[a[2], b[2], c[2]]}

The form with Flatten does not:

h @@@ Flatten[List @@ expr2, {2}]
{h["Fail!", b[0], c[0]], h["Fail!", b[1]], h["Fail!"]}

We can get around that with:

List @@ Flatten[h @@@ expr2, {2}, h]
{h[a[0], b[0], c[0]], h[a[1], b[1]], h[a[2]]}

Which could be generalized as:

raggedThread[x : h1_[h2_[___] ..]] := h2 @@ Flatten[h1 @@@ x, {2}, h1]

raggedThread[expr2]
{h[a[0], b[0], c[0]], h[a[1], b[1]], h[a[2]]}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371