3
$\begingroup$

So I'm wanting to index the sublists within a list using another list. So I have

x = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}

And I want the 2nd term of the first sublist, 1st term of the 2nd sublist, 3rd term of the 3rd sublist, i.e. I want output {2,4,9} or {{2},{4},{9}}

This is a simple example of a generalised problem, where x might be several thousand elements long with each element being a list with thousands of elements, and I might want to use a function like 'Take' instead of indexing, e.g. I might want to take the first 2 terms of the first list, the first term of the second list and the first 3 terms of the 3rd list to get the output {{1,2},{4},{7,8,9}}.

I have discovered the Thread function, which gives the following:

In[386]:= Thread[g[{1, 2, 3}, {2, 1, 3}]]
Out[386]= {g[1, 2], g[2, 1], g[3, 3]}

Therefore, I figured if I define f as follows

f[p_, q_] := x[[p, q]];

I would be able to write

Thread[f[{1, 2, 3}, {2, 1, 3}]]

And return the value obtained by evaluating

{f[1, 2], f[2, 1], f[3, 3]}

Which is {2,4,9} as I require.

Indeed, Mathematica gives

In[384]:= {f[1, 2], f[2, 1], f[3, 3]}
Out[384]= {2, 4, 9}

But

In[387]:= Thread[f[{1, 2, 3}, {2, 1, 3}]]
Out[387]= {{2, 5, 8}, {1, 4, 7}, {3, 6, 9}}

Why is this happening? Why doesn't my method work? Is there a better way?

Many thanks,

H

$\endgroup$
2
  • 1
    $\begingroup$ Depth of your list is not 3. So f [1,2,3] doesn't make sense $\endgroup$ Jan 5, 2018 at 13:08
  • $\begingroup$ Apply is probably not what you want here, but nevertheless: x[[##]] & @@@ Transpose[{Range@Length@x, {;; 2, 1, 1 ;;}}] -> {{1, 2}, 4, {7, 8, 9}} $\endgroup$
    – user1066
    Jan 5, 2018 at 14:57

2 Answers 2

2
$\begingroup$

Why is this happening?

Thread >> Possible Issues:

Thread evaluates the whole expression before threading.
MapThread takes the function and its arguments separately.

So you can wrap the first argument of Thread with Unevaluated to prevent evaluation before threading and get the desired result:

Thread[Unevaluated@f[{1, 2, 3}, {2, 1, 3}]]

{2, 4, 9}

Also

MapThread[f, {{1, 2, 3}, {2, 1, 3}}]
Inner[f, {1, 2, 3}, {2, 1, 3}, List]
MapIndexed[x[[#2[[1]], #]] &, {2, 1, 3}]
f @@@ Thread[{{1, 2, 3}, {2, 1, 3}}]
f @@@ Transpose[{{1, 2, 3}, {2, 1, 3}}]
Extract[x, MapIndexed[{#2[[1]], #} &, {2, 1, 3}]]

{2, 4, 9}

$\endgroup$
2
$\begingroup$

Since

f[{1, 2, 3}, {2, 1, 3}]

{{2, 1, 3}, {5, 4, 6}, {8, 7, 9}}

You get

Thread[{{2, 1, 3}, {5, 4, 6}, {8, 7, 9}}]

{{2, 5, 8}, {1, 4, 7}, {3, 6, 9}}

Instead you could use MapThread or Diagonal

Diagonal[Transpose[x][[{2, 1, 3}]]]    (* or Diagonal[x[[All, {2, 1, 3}]]] *)
MapThread[#[[#2]] &, {x, {2, 1, 3}}]
MapThread[#[[;; #2]] &, {x, {2, 1, 3}}]

{2, 4, 9}
{2, 4, 9}
{{1, 2}, {4}, {7, 8, 9}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.