3
$\begingroup$

As an assignment I need to re-implement Position. I've managed to do this except for one small thing, the resulting list is not in the current format. The following piece of code is what I have so far.

findPosition[lst_, x_] := Module[{output = {}, index = 1}, For[index = 1, index <= Length[lst], index++, If[lst[[index]] == x, AppendTo[output, {index}], False, If[MemberQ[lst[[index]], x], AppendTo[output, Map[{index, #} &, findPosition[lst[[index]], x]]]; False ]; (* If *) ] (* If *) ]; (* For *) Return[output] ] (* Module *) 

This gives the following output:

findPosition[{1, 2, {3, 2, 1}, {1, {4, 2, 1}, 2, {2, 6}}, {2, 6}}, 2] {{2}, {{3, {2}}}, {{4, {{2, {2}}}}, {4, {3}}, {4, {{4, {1}}}}}, {{5, {1}}}} 

While the original gives:

Position[{1, 2, {3, 2, 1}, {1, {4, 2, 1}, 2, {2, 6}}, {2, 6}}, 2] {{2}, {3, 2}, {4, 2, 2}, {4, 3}, {4, 4, 1}, {5, 1}} 

Am I doing something wrong or is there a way to make my result match the one from the original?

I've tried things using Flatten, but it's hard to control what is flattened and what is not. The closest I've come to is {{2}, {{3, 2}}, {{4, 2, 2}, {4, 3}, {4, 4, 1}}, {{5, 1}}} using

AppendTo[output, Map[Flatten[{index, #}] &, FindPosition[lst[[index]], x]]]; 
$\endgroup$
1
  • 1
    $\begingroup$ Recursion was designed for list-manipulation algorithms. Perhaps you could express findPosition[lst_, x_] in terms of findPosition[Most[lst], x] and findPosition[Rest[lst], x]. $\endgroup$ Commented Dec 10, 2012 at 21:00

1 Answer 1

7
$\begingroup$

Your code will only work for nests that have two levels of nesting due to how you are mapping the index, but if this is fine, then the solution is to just Flatten the recursive call before you append it to output, and then Flatten the output of findPosition to get rid of some of the trailing braces. These changes give the following (NOTE: we also add and extra pair of {} to the single element case so the final Flatten works)

findPosition[lst_, x_] := Module[{output = {}, index = 1}, For[index = 1, index <= Length[lst], index++, If[lst[[index]] == x, AppendTo[output, {{index}}], False, If[MemberQ[lst[[index]], x], AppendTo[output, Map[Flatten[{index, #}] &, findPosition[lst[[index]], x]]]; False];(*If*) ] (*If*) ];(*For*) Return[output] ] (*Module*) 

with the final wrapper:

myPosition[lst_, x_] := Flatten[findPosition[lst, x], 1] 

Now if we want do deal with arbirarly nested output we can do the following:

myPosition[lst_, x_] := First@Last@Reap[MapIndexed[If[MatchQ[#1, x], Sow[#2]] &, lst, Infinity];] 

which works for all input, and should be much faster.

$\endgroup$
2
  • 2
    $\begingroup$ In the last solution you should use MatchQ[#1, x] not #1==x. Position works on patterns not just strict equality. $\endgroup$ Commented Dec 11, 2012 at 10:42
  • $\begingroup$ @Gabriel Thank you, that really helped a lot. $\endgroup$ Commented Dec 11, 2012 at 16:09

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.