Grouping and repeating the grouped rows inside a matrix
m = {
{3, 1, 2},
{0, 5, 1},
{1, 4, 2},
{0, 6, 9},
{0, 4, 7},
{2, 6, 8}
};
Flatten[ConstantArray[#, #[[1, 1]]] & /@ Split[m, #2[[1]] == 0 &], 2]
$\left( \begin{array}{ccc} 3 & 1 & 2 \\ 0 & 5 & 1 \\ 3 & 1 & 2 \\ 0 & 5 & 1 \\ 3 & 1 & 2 \\ 0 & 5 & 1 \\ 1 & 4 & 2 \\ 0 & 6 & 9 \\ 0 & 4 & 7 \\ 2 & 6 & 8 \\ 2 & 6 & 8 \\ \end{array} \right)$
Here is the explanation for the above one-line code:
Flatten[ConstantArray[#, #[[1, 1]]] & /@ Split[m, #2[[1]] == 0 &], 2]
- First, Split function scans through the matrix m by taking two consecutive rows (#1, #2) and checks for the condition such that the 2nd row's first element is equal to zero (#2[[1]] == 0&), if it is True then it will add it to the group, otherwise it will add a split and start a new group, thereby grouping the matrix as show in the above example figure in the question section.
- Then, ConstantArray function is mapped (/@) onto the grouped (split) matrix such that it will replicate the grouped rows inside the matrix, "1st row's first element" (#[[1, 1]]) number of times, thereby replacing grouped rows with repeated rows.
- Finally, Flatten function flattens out the resultant list by removing all the unwanted curly braces up to the 2nd level, thereby creating the final resultant matrix.
This could be a starter for discussions:
A = RandomInteger[{0, 3}, {6, 3}];
idx = Pick[Range[Length[A]], Unitize[A[[All, 1]]], 1];
B = Join @@ MapThread[
Join @@ ConstantArray[A[[#1 ;; #2]], A[[#1, 1]]] &,
{
idx,
Append[Rest@idx - 1, Length[A]]
}
];
Hm. Building the list of rows first and to read from A
only once seems to be slightly faster.
idx = Pick[Range[Length[A]], Unitize[A[[All, 1]]], 1];
B2 = A[[
Join @@ Join @@ MapThread[
ConstantArray[Range[#1, #2], #3] &,
{idx, Append[Rest@idx - 1, Length[A]], A[[idx, 1]]}
]
]];
m = {{3, 1, 2}, {0, 5, 1}, {1, 4, 2}, {0, 6, 9}, {0, 4, 7}, {2, 6, 8}}
SequenceReplace[m, seq : {{x_ /; x > 0, __},
Repeated[{0, __}, {0, Infinity}]} :> Table[seq, x]]
Flatten[%, 2]