• minHeight() возвращает число, показывающее минимальную высоту, которую требует ячейка (выраженную в строчках)
• minWidth() возвращает число, показывающее минимальную ширину, которую требует ячейка (выраженную в символах)
• draw(width, height) возвращает массив длины >height
, содержащий наборы строк, каждая из которых шириной в >width
символов. Это содержимое ячейки.
Я буду использовать функции высшего порядка, поскольку они здесь очень уместны.
Первая часть программы вычисляет массивы минимальных ширин колонок и высот строк для матрицы ячеек. Переменная >rows
будет содержать массив массивов, где каждый внутренний массив – это строка ячеек.
>function rowHeights(rows) {
> return rows.map(function(row) {
> return row.reduce(function(max, cell) {
> return Math.max(max, cell.minHeight());
> }, 0);
> });
>}
>function colWidths(rows) {
> return rows[0].map(function(_, i) {
> return rows.reduce(function(max, row) {
> return Math.max(max, row[i].minWidth());
> }, 0);
> });
>}
Используя переменную, у которой имя начинается с (или полностью состоит из) подчёркивания (>_
), мы показываем тому, кто будет читать код, что этот аргумент не будет использоваться.
Функция >rowHeights
не должна вызвать затруднений. Она использует >reduce
для подсчёта максимальной высоты массива ячеек, и заворачивает это в >map
, чтобы пройти все строки в массиве >rows
.
Ситуация с >colWidths
посложнее, потому что внешний массив – это массив строк, а не столбцов. Я забыл упомянуть, что >map
(как и >forEach
, >filter
и похожие методы массивов) передаёт в заданную функцию второй аргумент – индекс текущего элемента. Проходя при помощи >map
элементы первой строки и используя только второй аргумент функции, >colWidths
строит массив с одним элементом для каждого индекса столбца. Вызов >reduce
проходит по внешнему массиву >rows
для каждого индекса, и выбирает ширину широчайшей ячейки в этом индексе.
Код для вывода таблицы:
>function drawTable(rows) {
> var heights = rowHeights(rows);
> var widths = colWidths(rows);
> function drawLine(blocks, lineNo) {
> return blocks.map(function(block) {
> return block[lineNo];
> }).join(" ");
> }
> function drawRow(row, rowNum) {
> var blocks = row.map(function(cell, colNum) {
> return cell.draw(widths[colNum], heights[rowNum]);
> });
> return blocks[0].map(function(_, lineNo) {
> return drawLine(blocks, lineNo);
> }).join("\n");
> }
> return rows.map(drawRow).join("\n");
>}
Функция >drawTable
использует внутреннюю функцию >drawRow
для рисования всех строк, соединяя их через символы новой строки.