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$
2
  • $\begingroup$ Is this always going to be a nice array? $\endgroup$
    – Kuba
    Oct 29, 2015 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, 2015 at 16:15

3 Answers 3

12
$\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$
2
  • $\begingroup$ Using Listable! So smart! +1 $\endgroup$
    – matheorem
    Oct 30, 2015 at 1:10
  • $\begingroup$ @matheorem Thank you! $\endgroup$
    – Michael E2
    Oct 30, 2015 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$
7
  • $\begingroup$ Ah, of course :) p.s. I find slot-free coding quite nice lately so: MapIndexed[ Rule, ...] $\endgroup$
    – Kuba
    Oct 29, 2015 at 16:22
  • $\begingroup$ Nice!!! thank you Kuba. $\endgroup$
    – kglr
    Oct 29, 2015 at 16:23
  • $\begingroup$ @kglr I recalled PositionIndex, but I forgot MapIndex. Thank you for your answer $\endgroup$
    – matheorem
    Oct 29, 2015 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, 2015 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, 2015 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$
1
  • $\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, 2015 at 16:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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