Well, I found the whole z1, z2 logic a bit unreadable, so I did it a bit differently:
var m = 3;
var n = 4;
var a = new Array();
var b = 0;
for(var i = 0; i < m; i++) {
a[i] = new Array(n);
for(var j = 0; j < n; j++) {
a[i][j] = b;
b++;
}
}
var out = new Array();
for (var i = 1 - m; i < n; i++) {
var group = new Array();
for (var j = 0; j < m; j++) {
if ((i + j) >= 0 && (i + j) < n) {
group.push(a[j][i + j]);
}
}
out.push(group);
}
console.log(out);
Prints [[8], [4, 9], [0, 5, 10], [1, 6, 11], [2, 7], [3]]
to the console.
How it works
Your matrix construction gives you a rectangle like this (where your a
array is the set of rows):
0 1 2 3
4 5 6 7
8 9 10 11
Which means the diagonals are over this grid:
# # 0 1 2 3
# 4 5 6 7 #
8 9 10 11 # #
Now we're just looping over a skewed rectangle, that would look like this normalised:
# # 0 1 2 3
# 4 5 6 7 #
8 9 10 11 # #
Now you'll notice that for each row you add, you end up with an extra column (starting with a #
) and that the first column is now skewed by this amount (if you imagine holding the first row in place & sliding the rows below to the left). So for our outer for
loop (over the columns), the first column is effectively the old first column, 0
, minus the number of rows m
, plus 1
, which gives 0 - m + 1
or 1 - m
. The last column effectively stays in place, so we're still looping to n
. Then its just a matter of taking each column & looping over each of the m
rows (inner for
loop).
Of course this leaves you with a bunch of undefined
s (the #
s in the grid above), but we can skip over them with a simple if
to make sure our i
& j
are within the m
& n
bounds.
Probably slightly less efficient than the z1
/z1
version since we're now looping over the redundant #
cells rather than pre-calculating them, but it shouldn't make any real world difference & I think the code ends up much more readable.