4

How can we embed a counter in the Map function?

Consider a data set such as data = {{a, b, c, d}, {e, f}, {g, h, i}}. The desired function would output

{{0, a}, {0, b}, {0, c}, {0, d}, {1, e}, {1, f}, {2, g}, {2, h}, {2, i}}

Responders are not constrained to use Map.

N.B. The answer does not appear to be in Indexed Map Thread.

dantopa
  • 1,060
  • 5
  • 10

1 Answers1

4

I believe you are looking for MapIndexed, and possibly Join/Apply:

Join @@ MapIndexed[{#2[[1]] - 1, #} &, data, {2}]
{{0, a}, {0, b}, {0, c}, {0, d}, {1, e}, {1, f}, {2, g}, {2, h}, {2, i}}

If this is not what you want or you find it difficult to apply please update the question.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Perfect. Another great answer MrW. Thanks. – dantopa May 29 '15 at 17:47
  • @Mr. Wizard may I ask what is the difference in terms of efficiency if you map Flatten at the first level, i.e. Flatten[MapIndexed[{#2[[1]], #} &, data, {2}], 1] ? – Athanassios Aug 11 '16 at 11:59
  • 3
    @Athanassios First, although you may not have been writing technically, note that Flatten[foo, 1] is not mapping Flatten at levelspec {1}, i.e. Map[Flatten, foo, {1}], just in case that should become a point of confusion. I typically find that Join @@ is faster, but often more importantly it preserves packed arrays. Since MapIndexed does not return packed arrays the latter is not evident here. Take for example x = Range @ RandomInteger[{1, 7}, 5*^4]; then RepeatedTiming[Developer`PackedArrayQ @ Flatten[x, 1]] vs RepeatedTiming[Developer`PackedArrayQ[Join @@ x]] – Mr.Wizard Aug 11 '16 at 14:15
  • @Athanassios On my system (10.1.0 under Windows) the results are {0.0207, False} and {0.00256, True}. So not only is Join nearly an order of magnitude faster, but it returns a packed array with all the benefits that entails. Out of habit I therefore use Join @@ even when it may not be strictly superior, though again I think you will often find it faster even when working with unpacked lists. – Mr.Wizard Aug 11 '16 at 14:17
  • Sorry, you are right, I am not mapping Flatten, I am flattening mapping list. In my system Mathematica 10.3.1.0, Linux x86 (64-bit) this is the command Flatten[MapIndexed[{#2[[1]] - 1, #} &, data, {2}], 1] to get the same result as with your Join. – Athanassios Aug 11 '16 at 14:51
  • And, many thanks for the analysis you provide. It helps a lot to understand why Join is faster than Flatten. I am not familiar with packed arrays differences, as I cannot notice them, and I know little about the implementation of things behind the scene. It is great that you offer to many of us the opportunity to learn more about this exuberant programming language. – Athanassios Aug 11 '16 at 14:58
  • 1
    I have just found that there has been a lot of discussion in this community about packed vs unpacked arrays. This is one of the posts, thank you again for pointing me at the right direction to learn more http://mathematica.stackexchange.com/questions/3496/what-is-a-mathematica-packed-array?s=1|0.3972 – Athanassios Aug 11 '16 at 15:06
  • @Athanassios You're welcome; I am glad I could help. :-) – Mr.Wizard Aug 11 '16 at 15:15