11

I have the following (example) list:

list = {"b", "a", "b", "b", "a", "c", "c", "c", "d", "b", "aa"};

and want to distinguish its elements by appending a counter in the following manner:

ord = Ordering @ Ordering @ list;

Part[#, ord]& @ Flatten[#, 1]& @ 
   MapIndexed[{#1, Last @ #2}&, #, {2}] & @ Gather @ Sort @ list

{{"b", 1}, {"a", 1}, {"b", 2}, {"b", 3}, {"a", 2}, {"c", 1}, {"c", 2}, {"c", 3}, {"d", 1}, {"b", 4}, {"aa", 1}}

This solution is somehow "expensive" (three ordering / sorting) operations, so the question is:

Are there more efficient alternatives?

eldo
  • 67,911
  • 5
  • 60
  • 168

3 Answers3

11
Clear[f]
f[_] = 0;
(f[#] = f[#] + 1; {f[#], #}) & /@ list

{{1, "b"}, {1, "a"}, {2, "b"}, {3, "b"}, {2, "a"}, {1, "c"}, {2,
"c"}, {3, "c"}, {1, "d"}, {4, "b"}, {1, "aa"}}

C. E.
  • 70,533
  • 6
  • 140
  • 264
7
list = {"b", "a", "b", "b", "a", "c", "c", "c", "d", "b", "aa"}
c = Association[# -> 0 & /@ Union@list]
{#, c[#] += 1} & /@ list

{{"b", 1}, {"a", 1}, {"b", 2}, {"b", 3}, {"a", 2}, {"c", 1}, {"c", 2}, {"c", 3}, {"d", 1}, {"b", 4}, {"aa", 1}}

george2079
  • 38,913
  • 1
  • 43
  • 110
5

Functional style:

FoldPairList[With[{c = Lookup[#1, #2, 1]}, 
   {{#2, c}, Append[#1, #2 -> c + 1]}] &, <||>, list]
swish
  • 7,881
  • 26
  • 48