My request is a follow-up on this question:
Replacing duplicates instead of deleting them
What if we want to replace duplicated values not with a single value but with newly created values distinct from each other?
list = {1, 1, 1, 5, 3, 2, 2};
My first attempt was:
list //. {h___, x_Integer, m___, x_Integer, t___} :> {h, x, m,
RandomInteger[{1, Length @ list}], t}
{1, 3, 2, 5, 5, 4, 3}
This functions sometimes, but most of the time not. Why?
Then I found the following preliminary solution:
xlist = list //. {h___, x_Integer, m___, x_Integer, t___} :> {h, x, m, "x", t}
{1, "x", "x", 5, 3, 2, "x"}
c = Complement[Range @ Length @ xlist, Select[NumberQ] @ xlist];
p = Flatten @ Position[xlist, "x"];
rlist = AssociationThread[p -> c]
<|2 -> 4, 3 -> 6, 7 -> 7|>
plist = AssociationThread[Range @ Length @ xlist -> xlist]
<|1 -> 1, 2 -> "x", 3 -> "x", 4 -> 5, 5 -> 3, 6 -> 2, 7 -> "x"|>
Expected result:
<|plist, rlist|> // Values
{1, 4, 6, 5, 3, 2, 7}
Questions:
Why has
ReplaceRepeatedfailed?The list cannot contain elements higher than list length. For example, this wouldn't function:
list = {1, 1, 1, 5, 3, 999, 2}. How would you handle this case?Better / faster alternatives.
UniquePositionswould yield {1, 2, 3, 5, 4, 6, 7} not preserving the original positions of as many unique elements as possible. In this case3and2before the last7. $\endgroup$