1. Problem statement
I want to replace duplicated elements within a matrix with a placeholder value.
2. Example data
SeedRandom[0];
mat = RandomInteger[{1, 100}, {5, 5}];
mat // MatrixForm
There are several duplicated values between rows and one value, 68
, repeated within a row (I use duplicated
and repeated
as synonyms, meaning more than once
).
3. UniqueElements
Since V 13.1 there is UniqueElements
which deletes duplicated matrix elements,
but results in a ragged list, not showing the positions of the deleted values.
UniqueElements[mat] // MatrixForm
4. The solution found
PaddedSingles[mat_?MatrixQ, rep_ : 0] :=
(* intra row replacements *)
ReplaceRepeated[{h___, a_, m___, a_, t___} :> {h, a, m, rep, t}] /@
(* between rows replacements *)
Table[
mat[[i]] /. Alternatives @@ Union @ Flatten @ Delete[mat, {i}] :> rep,
{i, Length @ mat}]
5. Expected result
res = PaddedSingles[mat];
res // MatrixForm
Check
DeleteCases[res, 0, {2}] == UniqueElements[mat]
(* True *)
6. Further examples
mat = {{1, 0, 1}, {0, 1, 0}, {0, 0, 2}};
res = PaddedSingles[mat, x]
{{x, x, x}, {x, x, x}, {x, x, 2}}
DeleteCases[res, x, {2}] == UniqueElements[mat]
(* True *)
mat = {{0, 1}, {1, 0}};
res = PaddedSingles[mat, x]
{{x, x}, {x, x}}
DeleteCases[res, x, {2}] == UniqueElements[mat]
(* True *)
7. Question
Maybe I should be happy with this solution, but I always feel a little bad when I have to use Table
or iterators. Also, because of the mapped ReplaceRepeated
and iterated ReplaceAll
, my solution should become very slow when acting on large matrices. Reasons enough to ask for alternative methods.