# get position index for all element in a list

For example

mat={{a,b},{c,a,a}}


How to write a function posindex that posindex[mat] will give

{{a -> {1, 1}, b -> {1, 2}}, {c -> {2, 1}, a -> {2, 2}, a -> {2, 3}}


And the function should also work for more complex list, for example

{{a,b},{c,{a},a}}


What is more, it should also work for elements that are expr, eg

{{a,b},{c,{10a},a}}


Summary

I accept Michael E2's answer, because it is by far the only one works for all the above cases and the thought behind the function elempos is easy to understand.

kglr's solution has the advantage of using built-in function MapIndexed. It works fine for list that contains only atomic expr. But fails when there is both complex level and non-atomic expr. But it is a quite useful solution in many case, what is more it provides level control that elempos doesn't have.

• Is this always going to be a nice array?
– Kuba
Oct 29, 2015 at 16:13
• @Kuba Oh, good question, If the array is not complex, then it is rather easy. But the general case... Oct 29, 2015 at 16:15

Here's my attempt at a general solution, according to a generalization that counts an expression as an "element" of a List if it is on level 1 of the List and not inside a function that is not List.

elempos[expr_] := Module[{mark},
SetAttributes[mark, Listable];
Thread[Extract[expr, #] -> #] &@ Position[mark[expr], _mark]
]

Clear[f];
e = {{1}, {2, 3}, {4, Sqrt[5], {f[6, {7}]}},
MeijerG[{{I/3}, {}}, {{1/2, 1, 3/2}, {}}, -I]};
elempos[e]
(*
{1 -> {1, 1}, 2 -> {2, 1}, 3 -> {2, 2}, 4 -> {3, 1},
Sqrt[5] -> {3, 2}, f[6, {7}] -> {3, 3, 1},
MeijerG[{{I/3}, {}}, {{1/2, 1, 3/2}, {}}, -I] -> {4}}
*)

• Using Listable! So smart! +1 Oct 30, 2015 at 1:10
• @matheorem Thank you! Oct 30, 2015 at 10:09
MapIndexed[# -> #2 &, mat, {2}]
(* {{a -> {1, 1}, b -> {1, 2}}, {c -> {2, 1}, a -> {2, 2}, a -> {2, 3}}} *)


or

MapIndexed[Rule, mat, {2}] (* thanks: Kuba *)


Alternatively,

MapIndexed[Rule, mat, {-1}]
(* {{a -> {1, 1}, b -> {1, 2}}, {c -> {2, 1}, a -> {2, 2}, a -> {2, 3}}} *)

MapIndexed[Rule, {{a, b}, {c, {a}, a}}, {-1}]
(* {{a -> {1, 1}, b -> {1, 2}}, {c -> {2, 1}, {a -> {2, 2, 1}},  a -> {2, 3}}} *)

• Ah, of course :) p.s. I find slot-free coding quite nice lately so: MapIndexed[ Rule, ...]
– Kuba
Oct 29, 2015 at 16:22
• Nice!!! thank you Kuba.
– kglr
Oct 29, 2015 at 16:23
• @kglr I recalled PositionIndex, but I forgot MapIndex. Thank you for your answer Oct 29, 2015 at 16:24
• @matheorem, thank you for the vote. PositionIndex is new-in-v-10; i am still with v9.
– kglr
Oct 29, 2015 at 16:29
• @kglr Now your answer is rather perfect :) Though I have v10, I can't figure out the right way, what a shame! Oct 29, 2015 at 16:32

You can use this:

f = Thread[Flatten[#] -> Position[#, _, {-1}, Heads -> False]] &


One can probably create example complex enough to fail but let's say it's quite ok :)

f[ mat ]

{a -> {1, 1}, b -> {1, 2}, c -> {2, 1}, a -> {2, 2}, a -> {2, 3}}

• quite good! It also works for {{a,b},{c,{a},a}}, your function gives {a -> {1, 1}, b -> {1, 2}, c -> {2, 1}, a -> {2, 2, 1}, a -> {2, 3}}. I think this result is good. Though, I have to admit that I didn't think this complex case when I post the question :) Oct 29, 2015 at 16:21