11
$\begingroup$

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.

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

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}}
*)
$\endgroup$
  • $\begingroup$ Using Listable! So smart! +1 $\endgroup$ – matheorem Oct 30 '15 at 1:10
  • $\begingroup$ @matheorem Thank you! $\endgroup$ – Michael E2 Oct 30 '15 at 10:09
11
$\begingroup$
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}}} *)
$\endgroup$
  • $\begingroup$ Ah, of course :) p.s. I find slot-free coding quite nice lately so: MapIndexed[ Rule, ...] $\endgroup$ – Kuba Oct 29 '15 at 16:22
  • $\begingroup$ Nice!!! thank you Kuba. $\endgroup$ – kglr Oct 29 '15 at 16:23
  • $\begingroup$ @kglr I recalled PositionIndex, but I forgot MapIndex. Thank you for your answer $\endgroup$ – matheorem Oct 29 '15 at 16:24
  • $\begingroup$ @matheorem, thank you for the vote. PositionIndex is new-in-v-10; i am still with v9. $\endgroup$ – kglr Oct 29 '15 at 16:29
  • $\begingroup$ @kglr Now your answer is rather perfect :) Though I have v10, I can't figure out the right way, what a shame! $\endgroup$ – matheorem Oct 29 '15 at 16:32
8
$\begingroup$

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}}
$\endgroup$
  • $\begingroup$ 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 :) $\endgroup$ – matheorem Oct 29 '15 at 16:21

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.