Ну, я обнаружил, что вся логика z1, z2 немного нечитаема, поэтому я сделал это немного по-другому:
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);
Печать [[8], [4, 9], [0, 5, 10], [1, 6, 11], [2, 7], [3]]
на консоли.
Как это работает
Ваша матричная конструкция дает вам такой прямоугольник (где ваш a
массив - это набор строк):
0 1 2 3
4 5 6 7
8 9 10 11
Что означает, что диагонали находятся над этой сеткой:
# # 0 1 2 3
# 4 5 6 7 #
8 9 10 11 # #
Теперь мы просто зациклились на скошенном прямоугольнике, который выглядел бы следующим образом:
# # 0 1 2 3
# 4 5 6 7 #
8 9 10 11 # #
Теперь вы заметите, что для каждой добавляемой строки у вас будет дополнительный столбец (начиная с #
), и что первый столбец теперь перекошен на эту величину (если вы представляете, что удерживаете первую строку в поместите и сдвиньте ряды внизу слева). Таким образом, для нашего внешнего цикла for
(по столбцам) первый столбец фактически является старым первым столбцом, 0
, минус количество строк m
, плюс 1
, что дает 0 - m + 1
или 1 - m
. Последний столбец фактически остается на месте, поэтому мы все еще возвращаемся к n
. Тогда нужно просто взять каждый столбец и выполнить цикл по каждой из m
строк (внутренний цикл for
).
Конечно, у вас останется куча undefined
с (#
с в сетке выше), но мы можем пропустить их с помощью простого if
, чтобы убедиться, что наши i
& j
находятся в пределах m
& n
.
Возможно, немного менее эффективен, чем версия z1
/ z1
, поскольку теперь мы перебираем избыточные ячейки #
вместо предварительного их вычисления, но это не должно иметь никакого значения в реальном мире, и я думаю, код становится намного более читабельным.