ASCII table where field can have newlines

天涯浪子 提交于 2019-11-30 20:09:42

问题


I have following function that display ASCII table

        function ascii_table(array, header) {
            if (!array.length) {
                return '';
            }
            var lengths = array[0].map(function(_, i) {
                var col = array.map(function(row) {
                    if (row[i] != undefined) {
                        return row[i].length;
                    } else {
                        return 0;
                    }
                });
                return Math.max.apply(Math, col);
            });
            array = array.map(function(row) {
                return '| ' + row.map(function(item, i) {
                    var size = item.length;
                    if (size < lengths[i]) {
                        item += new Array(lengths[i]-size+1).join(' ');
                    }
                    return item;
                }).join(' | ') + ' |';
            });
            var sep = '+' + lengths.map(function(length) {
                return new Array(length+3).join('-');
            }).join('+') + '+';
            if (header) {
                return sep + '\n' + array[0] + '\n' + sep + '\n' +
                    array.slice(1).join('\n') + '\n' + sep;
            } else {
                return sep + '\n' + array.join('\n') + '\n' + sep;
            }
        }

the problem is when the cell contain new line I end up with something like this:

+---------------------+--------+-------+-----+-------------------------------+------------+---------------------+
| date                | nick   | email | www | comment                       | ip         | avatar              |
+---------------------+--------+-------+-----+-------------------------------+------------+---------------------+
| 2016-01-27 21:11:10 | stefan | kanev |     | dsfdsfsd
sdfsdf
sdfsdf
sdfdsf | 1308240552 | avatars/default.png |
+---------------------+--------+-------+-----+-------------------------------+------------+---------------------+

What should I change in my function to produce the result like this:

+---------------------+--------+-------+-----+----------+------------+---------------------+
| date                | nick   | email | www | comment  | ip         | avatar              |
+---------------------+--------+-------+-----+----------+------------+---------------------+
| 2016-01-27 21:11:10 | stefan | kanev |     | dsfdsfsd | 1308240552 | avatars/default.png |
|                     |        |       |     | sdfsdf   |            |                     |
|                     |        |       |     | sdfsdf   |            |                     |
|                     |        |       |     | sdfdsf   |            |                     |
+---------------------+--------+-------+-----+----------+------------+---------------------+

回答1:


You could modify the table and add the new rows to the table before before rendering it:

function ascii_table(array, header) {
    if (!array.length) {
        return '';
    }

    //added
    for (var i = array.length - 1; i >= 0; i--) {
        var row = array[i];
        var stacks = [];
        for (var j = 0; j < row.length; j++) {
            var newLines = row[j].split("\n");
            row[j] = newLines.shift();
            stacks.push(newLines);
        }
        var newRowsCount = stacks.reduce(function(a, b) {
            return a.length > b.length ? a : b;
        }).length;
        for (var k = newRowsCount - 1; k >= 0; k--) {
            array.splice(i + 1, 0, stacks.map(function(stackColumn) {
                return stackColumn[k] || "";
            }));
        }
    }
    //added

    var lengths = array[0].map(function(_, i) {
        var col = array.map(function(row) {
            if (row[i] != undefined) {
                return row[i].length;
            } else {
                return 0;
            }
        });
        return Math.max.apply(Math, col);
    });
    array = array.map(function(row) {
        return '| ' + row.map(function(item, i) {
            var size = item.length;
            if (size < lengths[i]) {
                item += new Array(lengths[i] - size + 1).join(' ');
            }
            return item;
        }).join(' | ') + ' |';
    });
    var sep = '+' + lengths.map(function(length) {
        return new Array(length + 3).join('-');
    }).join('+') + '+';
    if (header) {
        return sep + '\n' + array[0] + '\n' + sep + '\n' +
            array.slice(1).join('\n') + '\n' + sep;
    } else {
        return sep + '\n' + array.join('\n') + '\n' + sep;
    }
}

Output:

+---------------------+------+--------+-----+------------------+------------+---------------------+
| date                | nick | email  | www | comment          | ip         | avatar              |
+---------------------+------+--------+-----+------------------+------------+---------------------+
| 2016-01-28 11:40:59 | lol  | lol@lo |     | nocomment        | 1844311719 | avatars/default.png |
|                     |      | l.fr   |     | lol              |            |                     |
|                     |      |        |     | lol              |            |                     |
|                     |      |        |     | lol              |            |                     |
| 2016-01-10 15:13:59 | ehs  | what   |     | ente rm comment. | 1423172924 | avatars/default.png |
+---------------------+------+--------+-----+------------------+------------+---------------------+

(Added a new line in one email cell, to test new lines in multiple columns).




回答2:


This can be done without any modification of your code by expanding your array -- adding one new row for each extra line of the comment. The first row would be the same as before -- except that the comment cell contains only the first line of the comment. Every additional line would contain empty cells -- except the comment cell, which would contain that comment line.

I'd break out most of the functions for readability, but to keep with your coding style, it might look like this:

  array = array.reduce(function (carry, originalRow) {
    var commentLines = originalRow[4].split(/\n/g);

    var rows = commentLines.map(function (commentLine, rowIndex) {
        var newRow = originalRow.map(function (originalCellContent, columnIndex) {
            var cellContent = '';

            if (rowIndex === 0) {
                cellContent = originalCellContent;
            }
            if (columnIndex === 4) {
                cellContent = commentLine;
            }

            return cellContent;
        });
        carry.push(newRow);
    });

    return carry;
  }, []);

A fork of your fiddle is here, with this code added.




回答3:


Here it is: https://jsfiddle.net/zww557sh/1/

    function ascii_table(array, header) {
        if (!array.length) {
            return '';
        }
        var lengths = array[0].map(function(_, i) {
            var col = array.map(function(row) {
                if (row[i] != undefined) {
                    return row[i].length;
                } else {
                    return 0;
                }
            });
            return Math.max.apply(Math, col);
        });
        array = array.map(function(row, r) {
            // let's split the table cells to lines
            var cols = row.map(function(item, i){
              return item.split("\n")
            });
            // and calculate the max column-height in this row
            var maxH = (cols.reduce(function(i,j){return i.length > j.length ? i : j})).length;

            // here we manually build the string that will represent
            // this row of the table, including the "multi-line" cells
            var rowStr = "";
            // loop until the maximum cell height in this row
            for (h=0;h<maxH;h++) {
              rowStr += "| ";
              // loop on all the cells
              for (c=0;c<cols.length;c++) {
                if (c>0) rowStr += " | ";
                // item is the h'th in column c, but it might
                // be non existing, then we use ""
                var item = cols[c][h] || "";
                var size = item.length;
                // here we use the same padding
                if (size < lengths[c]) {
                  item += new Array(lengths[c]-size+1).join(' ');
                }
                rowStr += item;
              }
              rowStr += " |";
              if (h<maxH-1) rowStr += "\n";
            }
          return rowStr;
        });
        var sep = '+' + lengths.map(function(length) {
            return new Array(length+3).join('-');
        }).join('+') + '+';
        if (header) {
            return sep + '\n' + array[0] + '\n' + sep + '\n' +
                array.slice(1).join('\n') + '\n' + sep;
        } else {
            return sep + '\n' + array.join('\n') + '\n' + sep;
        }
    }

Output:

+---------------------+------+------------+-----+-----------------------+------------+---------------------+
| date                | nick | email      | www | comment               | ip         | avatar              |
+---------------------+------+------------+-----+-----------------------+------------+---------------------+
| 2016-01-28 11:40:59 | lol  | lol@lol.fr |     | nocomment             | 1844311719 | avatars/default.png |
|                     |      |            |     | lol                   |            |                     |
|                     |      |            |     | lol                   |            |                     |
|                     |      |            |     | lol                   |            |                     |
| 2016-01-10 15:13:59 | ehs  | what       |     | ente rm comment.      | 1423172924 | avatars/default.png |
+---------------------+------+------------+-----+-----------------------+------------+---------------------+


来源:https://stackoverflow.com/questions/35047522/ascii-table-where-field-can-have-newlines

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!