Javascript PrintTable

Date: 2021-09-28
(() => {
    const repeat = (char, length) => Array(length + 1).join(char);
    const ljust = (s, width, c = " ") => s.length < width ? s + repeat(c.slice(0, 1), width - s.length) : s; // padleft
    const rjust = (s, width, c = " ") => s.length < width ? repeat(c.slice(0, 1), width - s.length) + s : s; // padright
    function center(s, width, c = " ") { // padcenter
        if (s.length < width) {
            c = c.slice(0, 1);
            const len = width - s.length;
            const remain = (len % 2 === 0) ? "" : c;
            const pads = repeat(c, Math.floor(len / 2));
            return pads + s + pads + remain;
        } else
            return s;
    }
    const ALIGN = {
        LEFT: 0,
        CENTER: 1,
        RIGHT: 2
    };
    const printTable = (data) => {
        if (!Array.isArray(data)) return;
        if (data.length < 1) return new Error("Table should contain at least 1 row");
        const columns = [];
        const typeRow = data[1];
        const columnCount = typeRow.length;
        for (let c = 0; c < columnCount; c++) {
            const column = {
                index: c,
                name: `Col ${c}`,
                size: 0,
                align: ALIGN.LEFT
            };
            const type = typeof typeRow[c];
            if (type === "number") {
                column.align = ALIGN.RIGHT;
            }
            column.size = data.reduce((v, r) => Math.max(v, String(r[c]).length), 0);
            columns.push(column);
        }
        const tabledata = [];
        for (const row of data) {
            const rowdata = [];
            for (const col of columns) {
                const value = String(row[col.index]);
                if (col.align == ALIGN.CENTER) {
                    rowdata.push(center(value, col.size))
                } else  if (col.align == ALIGN.RIGHT) {
                    rowdata.push(rjust(value, col.size))
                } else {
                    rowdata.push(ljust(value, col.size));
                }
            }
            tabledata.push(`| ${rowdata.join(" | ")} |`);
        }
        const width = tabledata[0].length;
        const line = repeat("=", width);
        tabledata.splice(1, 0, line);
        tabledata.unshift(line);
        tabledata.push(line);
        return tabledata.join("\n");
    }

    const objsToTable = (data) => {
        const result = [];
        const columns = Object.keys(data[0]);
        let row = [];
        for (const c of columns) {
            row.push(c);
        }
        result.push(row);
        for (const item of data) {
            row = [];
            for (const c of columns) {
                row.push(item[c]);
            }
            result.push(row);
        }
        return result;
    };

    const data = [
        {"id":1,"first_name":"Hogan","last_name":"Egdal","age":55,"email":"hegdal0@t-online.de","gender":"Female","ip_address":"246.182.212.226"},
        {"id":2,"first_name":"Haily","last_name":"Cheales","age":56,"email":"hcheales1@mlb.com","gender":"Female","ip_address":"89.149.57.20"},
        {"id":3,"first_name":"Mandel","last_name":"Calken","age":39,"email":"mcalken2@mozilla.com","gender":"Genderfluid","ip_address":"146.82.130.243"},
        {"id":4,"first_name":"Meade","last_name":"Ongin","age":12,"email":"mongin3@technorati.com","gender":"Genderfluid","ip_address":"85.33.52.45"},
        {"id":5,"first_name":"Jeannie","last_name":"Balazs","age":22,"email":"jbalazs4@tripod.com","gender":"Bigender","ip_address":"124.200.22.70"},
        {"id":6,"first_name":"Leonie","last_name":"Mimmack","age":29,"email":"lmimmack5@chron.com","gender":"Genderfluid","ip_address":"140.108.128.252"},
        {"id":7,"first_name":"Inglis","last_name":"Daspar","age":80,"email":"idaspar6@odnoklassniki.ru","gender":"Agender","ip_address":"172.50.192.149"},
        {"id":8,"first_name":"Michal","last_name":"Itzik","age":41,"email":"mitzik7@pcworld.com","gender":"Genderqueer","ip_address":"164.224.49.132"},
        {"id":9,"first_name":"Vikki","last_name":"Edelheit","age":20,"email":"vedelheit8@dagondesign.com","gender":"Polygender","ip_address":"112.172.252.190"},
        {"id":10,"first_name":"Mallory","last_name":"Stamp","age":66,"email":"mstamp9@cnn.com","gender":"Genderfluid","ip_address":"51.223.32.46"}
    ];

    const out = printTable(objsToTable(data));
    console.log(out);
})();

Result

==================================================================================================
| id | first_name | last_name | age | email                      | gender      | ip_address      |
==================================================================================================
|  1 | Hogan      | Egdal     |  55 | hegdal0@t-online.de        | Female      | 246.182.212.226 |
|  2 | Haily      | Cheales   |  56 | hcheales1@mlb.com          | Female      | 89.149.57.20    |
|  3 | Mandel     | Calken    |  39 | mcalken2@mozilla.com       | Genderfluid | 146.82.130.243  |
|  4 | Meade      | Ongin     |  12 | mongin3@technorati.com     | Genderfluid | 85.33.52.45     |
|  5 | Jeannie    | Balazs    |  22 | jbalazs4@tripod.com        | Bigender    | 124.200.22.70   |
|  6 | Leonie     | Mimmack   |  29 | lmimmack5@chron.com        | Genderfluid | 140.108.128.252 |
|  7 | Inglis     | Daspar    |  80 | idaspar6@odnoklassniki.ru  | Agender     | 172.50.192.149  |
|  8 | Michal     | Itzik     |  41 | mitzik7@pcworld.com        | Genderqueer | 164.224.49.132  |
|  9 | Vikki      | Edelheit  |  20 | vedelheit8@dagondesign.com | Polygender  | 112.172.252.190 |
| 10 | Mallory    | Stamp     |  66 | mstamp9@cnn.com            | Genderfluid | 51.223.32.46    |
==================================================================================================
54040cookie-checkJavascript PrintTable