Given a list, e.g., target = {a, b, c, b, c, d, c, d, e, f, a, h, g}
, I want to generate a list containing the occurrence count of the corresponding element of the target list, e.g., {1, 1, 1, 2, 2, 1, 3, 2, 1, 1, 2, 1, 1}
for the example target. Target elements can be pretty much anything: atoms, sublists, etc. I'm using result = Module[{c}, c[_] = 0; ++c[#] & /@ #] &[target]
which works fine, but wonder if the wizards have a more efficient way.
Update: Came up with this while 'cigar thinking':
result = Module[{ordarg, ord},
ordarg[[ord]] =
Flatten[Range /@ (Tally[ordarg = #[[ord = Ordering[#]]]][[All, 2]])];
ordarg] &[target];
On numeric/symbol/etc. items, this clobbers my original method by orders of magnitude with large lists. It is also 2-3+ times faster even then the most excellent compiled example provided below by L.S. Interestingly, my original method is faster than this or the compiled version for string/character data. (L.S./M.W. et al, perhaps you can illuminate this?)
This is plenty fast for my needs, though I'm still of course interested in the real masters' ideas.
Module[{count}, count[_] = 0; List @@ (target /. a_String :> ++count[a])]
. Versions that work for any head that I could find is tiny bit slower. $\endgroup$Dispatch
in my solution becomes slower and consumes most of run time. $\endgroup$