ClearAll[replaceDuplicates]
replaceDuplicates[rep_: "X"] := Module[{f}, f[y_] := (f[y] = rep; y); f /@ #] &
Examples:
replaceDuplicates[] @ {1, 2, 3, 2, 5, 2, 1, 5, 5, 2, 3, 3, 7}
{1, 2, 3, "X", 5, "X", "X", "X", "X", "X", "X", "X", 7}
replaceDuplicates[Nothing] @ {1, 2, 3, 2, 5, 2, 1, 5, 5, 2, 3, 3, 7}
{1, 2, 3, 5, 7}
Alternatively:
ClearAll[replaceDuplicates2]
replaceDuplicates2[rep_: "X"] := Module[{y = #},
y[[Join @@ (Rest /@ Values @ PositionIndex[y])]] = rep; y] &
Examples:
replaceDuplicates2[] @ {1, 2, 3, 2, 5, 2, 1, 5, 5, 2, 3, 3, 7}
{1, 2, 3, "X", 5, "X", "X", "X", "X", "X", "X", "X", 7}
replaceDuplicates2[Nothing] @ {1, 2, 3, 2, 5, 2, 1, 5, 5, 2, 3, 3, 7}
{1, 2, 3, 5, 7}
f[y_] := (f[y] = rep; y)which will execute the first time it sees a valueyand first perform the assignmentf[y] = repand then returny. That is why the values do not get replaced with"X"the first time they are seen. On the next time the valueyis seen, because of the assignmentf[y] = rep, the function simply returnsy. All of this is wrapped inModuleso it's cleaned up properly and then the function is mapped over the list of arguments. – b3m2a1 Apr 25 '21 at 02:54freturnsafirst time it encountersaand redefines itself to return"X"next time it encountersa. – kglr Apr 25 '21 at 03:38Clear[f](but notClearAll!) at the end before returning the result, otherwisefwill not be garbage-collected and will hang around indefinitely after the call toreplaceDuplicates- and if you call it multiple times, then just as many differentfs will be left hanging around. – Leonid Shifrin Apr 26 '21 at 11:56