I would like to know if there is a nice functional way to code up a MapList which applies f to each element of expr and returns a list of the results obtained.

Here is my implementation:

MapList[f_, expr_] := List @@ (MapIndexed[ReplacePart[expr, #2 -> f[#1]] &, expr])

It works in this test case:

myData = head[a, b, c, d];
MapList[f, myData]

(*  {head[f[a],b,c,d], head[a,f[b],c,d], head[a,b,f[c],d], head[a,b,c,f[d]]}  *)

But if the head has some DownValues or funny Attributes like this:

SetAttributes[head, Flat];
MapList[f, myData]

(*  {f[a], b, c, d, a, f[b], c, d, a, b, f[c], d, a, b, c, f[d]}  *)

it gives the wrong result (because the Flat is kicking in before List @@ swaps out the head of the output).

How do I program a ListMap that is as fast and robust against possible definitions attached to head?

  • 6
    $\begingroup$ Something like MapAt[f,expr,#]&/@Range[Length[expr]]? $\endgroup$ – chuy May 23 '18 at 19:56
  • $\begingroup$ Yup! And also the variation Array[MapAt[f,expr,#]&,Length[expr]] works. $\endgroup$ – QuantumDot May 23 '18 at 21:19
  • 4
    $\begingroup$ I'm voting to close this question as off-topic because it is a duplicate of stackoverflow.com/questions/7944549/a-maplist-function $\endgroup$ – QuantumDot May 24 '18 at 2:16

A asked something not too dissimilar some years ago:


My implementation from the question itself:

MapList[f_, expr_, level_: 1] :=
 MapAt[f, expr, #] & /@
  Position[expr, _, level, Heads -> False]

This happens to handle your example:

myData = head[a, b, c, d];
SetAttributes[head, Flat];
MapList[f, myData]
{head[f[a], b, c, d], head[a, f[b], c, d], head[a, b, f[c], d], head[a, b, c, f[d]]}

I suspect you may find the answers I recieved of interest as well.

| improve this answer | |
  • $\begingroup$ Oh, I totally missed that! Please mark my question as a duplicate. Your answer and the answers there are quite helpful. $\endgroup$ – QuantumDot May 24 '18 at 2:15

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