5
$\begingroup$

I have a Table with elements {{i1, j1, k1},{i2, j2, k2},...}

I wanted to store the values of {{a1, b1, c1},{a2, b2, c2},...} in a table where

a = f(i, j, k)
b = g(i, j, k)
c = h(i, j, k)

are simple functions of i, j, and k.

This seems to be quite a simple task but I can't seem to access the values properly, and am not familiar with Thread, Transpose, Interpolation, etc, so any suggestions on how to efficiently do the task would be very helpful.

$\endgroup$
8
  • $\begingroup$ Through /@ {f, g, h} /@ {{i1, j1, k1}, {i2, j2, k2}} ? $\endgroup$ May 28, 2018 at 2:49
  • 2
    $\begingroup$ ... or Through[{f,g,h}@##]&@@@{{i1, j1, k1}, {i2, j2, k2}} or Through[{f, g, h} @@ #] & /@ {{i1, j1, k1}, {i2, j2, k2}} $\endgroup$
    – kglr
    May 28, 2018 at 4:03
  • $\begingroup$ @AccidentalFourierTransform It is not quite correct. $\endgroup$ May 28, 2018 at 7:15
  • $\begingroup$ @kglr - In general how do I call all the Table elements {{i_n, j_n, k_n}...}? And could you elaborate a little on what exactly your syntax does? $\endgroup$ May 28, 2018 at 13:02
  • 1
    $\begingroup$ Sarah, Through[{f,g,h}@##]&@@@yourTable should transform each triple {i,j,k} to {f[i,j,k],g[i,j,k],h[i,j,k]}. How it works: (1) Through[{f, g, h}@arg] gives {f[arg],g[arg],h[arg]. (2) The form @@@ is short for Apply at level 1 (see Apply). So, foo@@@{{a,b,c},{u,s,t},{v,w,z}} gives {foo[a,b,c],foo[u,s,t],foo[v,w,z]}. ((In contrast, Maping foo on the same list, foo/@{{a,b,c},{u,s,t},{v,w,z}} gives {foo[{a,b,c}], foo[{u,s,t}],foo[{v,w,z}]}). $\endgroup$
    – kglr
    May 28, 2018 at 13:27

4 Answers 4

4
$\begingroup$

Let me start by generating a small sample from a table like yours, for demonstration:

table = Array[Through[{i, j, k}[#]] &, 2]

(* Out:
{{i[1], j[1], k[1]}, {i[2], j[2], k[2]}}
*)

In my view, perhaps the most immediately readable approach to your problem might be the following:

{f[##], g[##], h[##]}& @@@ table

(* Out:
{{f[i[1], j[1], k[1]], g[i[1], j[1], k[1]], h[i[1], j[1], k[1]]},
 {f[i[2], j[2], k[2]], g[i[2], j[2], k[2]], h[i[2], j[2], k[2]]}}
*)

You will want to take a look at the docs for Apply if this syntax or the equivalent Apply[function, input, {1}] are unfamiliar to you.


A more compact way to generate that functional expression is the following, as suggested by @kglr in comments:

Through[{f, g, h}[##]]& @@@ table

You can convince yourself that the Through expression essentially generates a functional form equivalent to the one I first proposed above as follows:

Evaluate[ Through[{f, g, h}[##]] ] &

(* Out: {f[##1], g[##1], h[##1]} & *)

where ##1 is equivalent to ## (see SlotSequence).

$\endgroup$
4
$\begingroup$
table = {{i[1], j[1], k[1]}, {i[2], j[2], k[2]}};

Using ComapApply (new in 14.0)

ComapApply[{f, g, h}] /@ table

returns

{{f[i[1], j[1], k[1]], g[i[1], j[1], k[1]], h[i[1], j[1], k[1]]}, 
 {f[i[2], j[2], k[2]], g[i[2], j[2], k[2]], h[i[2], j[2], k[2]]}}

Compare to Query

Query[All, Apply /@ {f, g, h}] @ table

(* same result *)

$\endgroup$
2
$\begingroup$

Since I use an older version (v12.2.0), the Co-Map-Apply can be implemented using:

list = {{i1, j1, k1}, {i2, j2, k2}, {i3, j3, k3}}

Transpose@Outer[Compose, Map[Apply][{f, g, h}], list, 1]

{{f[i1, j1, k1], g[i1, j1, k1], h[i1, j1, k1]}, {f[i2, j2, k2],
g[i2, j2, k2], h[i2, j2, k2]}, {f[i3, j3, k3], g[i3, j3, k3], h[i3, j3, k3]}}

$\endgroup$
2
$\begingroup$
table = {{i[1], j[1], k[1]}, {i[2], j[2], k[2]}};

Another way using BlockMap:

Transpose@BlockMap[Sequence @@ {f @@@ #, g @@@ #, h @@@ #} &, table, {2}]
{{f[i[1], j[1], k[1]], g[i[1], j[1], k[1]], h[i[1], j[1], k[1]]}, 
 {f[i[2], j[2], k[2]], g[i[2], j[2], k[2]], h[i[2], j[2], k[2]]}}

Or using SubsetMap:

SubsetMap[{f @@ #, g @@ #, h @@ #} &, table[[#]], All] & /@ Range@Length@table
{{f[i[1], j[1], k[1]], g[i[1], j[1], k[1]], h[i[1], j[1], k[1]]}, 
 {f[i[2], j[2], k[2]], g[i[2], j[2], k[2]], h[i[2], j[2], k[2]]}}
$\endgroup$

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .