3
$\begingroup$

This question already has an answer here:

This is a candidate for a duplicate (probably from the documentation) but I've ironically failed to find the direct analog so far.

I have an arbitrary nested list, say:

anl = {first , second, {x, y, z}, {a, {b, c}}}

I need some MMA way to apply f to positions poss if I do not know them:

poss = {{1}, {2}, {3, 1}, {3, 2}, {3, 3}, {4, 1}, {4, 2, 1}, {4, 2, 2}}

So I need 1) an analog to:

MapAt[f, anl, poss]

{f[first], f[second], {f[x], f[y], f[z]}, {f[a], {f[b], f[c]}}}

2) a way to get poss.

Stuck a bit. Thank you for any constructive help in advance.

$\endgroup$

marked as duplicate by Oleksandr R., march, dr.blochwave, MarcoB, Community Dec 21 '15 at 5:12

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    $\begingroup$ Do you need the positions or is something like anl /. a_Symbol :> f[a] /. f[List] :> List acceptable? $\endgroup$ – march Dec 20 '15 at 20:57
  • $\begingroup$ @march, I need to operate with leaves of large lists and associations, so positions are not a value in itself. Anyway, Replacement would qualifiy as a useful alternative. $\endgroup$ – garej Dec 20 '15 at 21:05
  • 3
    $\begingroup$ Is this what you need? l = Map[f, anl, {-1}]; Most /@ Position[l, f]? $\endgroup$ – Kuba Dec 20 '15 at 21:06
  • 4
    $\begingroup$ related: 99603 $\endgroup$ – Kuba Dec 20 '15 at 21:08
  • 2
    $\begingroup$ @Kuba This one?: mathematica.stackexchange.com/questions/98170/… $\endgroup$ – Michael E2 Dec 21 '15 at 1:15
4
$\begingroup$

Is this what you need ? :

{result, poss0} = Reap[MapIndexed[(Sow[#2]; f[#1]) &, anl, {-1}]];
poss=poss0[[1]]
result

{{1}, {2}, {3, 1}, {3, 2}, {3, 3}, {4, 1}, {4, 2, 1}, {4, 2, 2}}
{f[first], f[second], {f[x], f[y], f[z]}, {f[a], {f[b], f[c]}}}

The level {-1} corresponds to all the leaves of the expression.

$\endgroup$
  • $\begingroup$ yes, that is what I need. Thank you for Reap/Sow solution. Frankly, I thought that some simple function exists that map at all final leaves of the tree. $\endgroup$ – garej Dec 20 '15 at 20:45
  • $\begingroup$ @garej yes, it does. You can use Map[f, anl, {-1}]. But in your question you wanted the positions of the leaves as well, and I think andre's solution is one of the most obvious ways to get this. Another could be poss = Level[MapIndexed[f, anl, {-1}], {-2}]. $\endgroup$ – Oleksandr R. Dec 20 '15 at 21:00
  • $\begingroup$ @OleksandrR., you are right, Map[f, anl, {-1}] solves a half of the problem and it is up to you to decide (I can edit the post to add the link). I'm glad to get several useful ways of doing this anyway. $\endgroup$ – garej Dec 20 '15 at 21:19
  • $\begingroup$ @garej and the other half can be solved with Level as also discussed, and as I showed in my comment above. So, if you're happy with it, I'll vote. Please note that questions closed as duplicates will not be deleted: it's just a way to organise the site. $\endgroup$ – Oleksandr R. Dec 20 '15 at 21:32
  • $\begingroup$ @Oleksandr R. @garej I don't know if in the OP mind f is intended to stay as a simple symbol or is intended to become a more complex expression, for exemple a function like x^2+x+1. In that case the solution poss=Level[MapIndexed[f,anl,{-1}],{-2}] doesn't work. $\endgroup$ – andre314 Dec 20 '15 at 22:05
4
$\begingroup$

See Position

Position[anl, v_ /; ListQ[v] != True, Infinity, Heads -> False]
(* {{1}, {2}, {3, 1}, {3, 2}, {3, 3}, {4, 1}, {4, 2, 1}, {4, 2, 2}} *)
$\endgroup$
  • $\begingroup$ I do not need {4} and {4,2}, and {3}. I've found that positions and manually deleted unneeded =)) And (1) analog would be nice to have. $\endgroup$ – garej Dec 20 '15 at 20:37
  • $\begingroup$ See update. Added patter criteria to ignore List $\endgroup$ – Edmund Dec 20 '15 at 20:39
3
$\begingroup$
anl = {first, second, {x, y, z}, {a, {b, c}}};

pos = Position[anl, a_ /; Head@a =!= List, Heads -> False]

{{1}, {2}, {3, 1}, {3, 2}, {3, 3}, {4, 1}, {4, 2, 1}, {4, 2, 2}}

Or

pos = Position[anl, Except[_List], Heads -> False];

MapAt[g, anl, pos]

{g[first], g[second], {g[x], g[y], g[z]}, {g[a], {g[b], g[c]}}}

I would probably use

anl /. a_Except[_List] :> g@a
$\endgroup$

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