Matti's CS Notebook

Writing code for writing a simple table

The $\LaTeX$ syntax for writing table is simple. One needs to tell $\LaTeX$ that table is about to be rendered using the \begin{array} and \end{array} declaration. The columns of a $\LaTeX$ table align to left by default, but to center column elements, additional pair of can be written immediately after the \begin{array}, like in the following example:

\begin{array}{c c c}
    X & Y & Z \\
    1 & 2 & 3 \\
    4 & 5 & 6
\end{array}

Column are separated with & and new line is started with \\.

When this $\LaTeX$ is then given to suitable $\LaTeX$ engine, like pdfTeX or MathJax, the engine outputs a table like

$$ \begin{array}{c c c} X & Y & Z \\ 1 & 2 & 3 \\ 4 & 5 & 6 \end{array} $$

These tables can be then be stylized by horizontal or vertical separators. If the first row and column of the above table needs to be separated from the rest of the rows and columns, one can add \hline and | (i.e., the vertical bar) to the $\LaTeX$ markdown by writing

\begin{array}{c | c c}
    X & Y & Z \\ \hline
    1 & 2 & 3 \\
    4 & 5 & 6
\end{array}

This makes the $\LaTeX$ to render the table

$$ \begin{array}{c | c c} X & Y & Z \\ \hline 1 & 2 & 3 \\ 4 & 5 & 6 \end{array} $$

Let’s say then that there’s a need for creating table with multiple rows and columns in order to render multiple computation results. In particular, let’s say that one needs to fill the rows of a table like,

$$ \begin{array}{ | c | c | c | c | c | c | c | c | } \hline f(n) & 1 \ \text{s} & 1 \ \text{min} & 1 \ \text{h} & 1 \ \text{d} & 1 \ \text{m} & 1 \ \text{y} & 1 \ \text{c} \\ \hline \end{array} \tag{1} $$
[Table viewable in horizontal mode]

where $f(t)$ is a predefined function of maximum size input $n$ that can be computed in a given time duration $t$ in milliseconds, listed in the rest of the six columns. For example, $f(n)$ could be equal to $n$ at one row and to $\frac{1}{2}n$ at second.

Even with two rows, this results in twelve calculations to be done for each column at each row for each time duration $t$. And if the number of rows increase by width of the table and the number of calculations increases, so maybe these calculations could be automated with code that computes all the values in each cell automatically. This means coming up with code that outputs string in the $\LaTeX$ array format as described in the above examples which is then rendered by $\LaTeX$ engine just like the examples above.

One can start coding this by defining empty HTML <div> object to the page the table is to be rendered, and since it’s just a single one-page object, the table can be given just a simple unique id, such as “tbl”, for example. This tbl can be declared then as

<div id = "tbl"></div>

This table can be identified from the HTML DOM Tree of objects by writing the first line of our Javascript code

let tbl = document.getElementById("tbl");

Then the first, or the header line of the table, can be inserted into the tbl Javascript object by writing

tbl.innerHTML = 
    '\\begin{array}{ | c | c | c | c | c | c | c | c | } \\hline'
        + '\n'
        + '    ' // Row indentation
        + 'f(n) &'
        + ' 1 \\ \\text{s} &'
        + ' 1 \\ \\text{min} &'
        + ' 1 \\ \\text{h} &'
        + ' 1 \\ \\text{d} &'
        + ' 1 \\ \\text{m} &'
        + ' 1 \\ \\text{y} &'
        + ' 1 \\ \\text{c}'
        + ' \\\\ ' + '\\hline' + '\n'
        + '\\end{array}';

The $\LaTeX$ generated by the above code is then,

\begin{array}{ | c | c | c | c | c | c | c | c | } \hline
   f(n) & 1 \ \text{s} & 1 \ \text{min} & 1 \ \text{h} & 1 \ \text{d} & 1 \ \text{m} & 1 \ \text{y} & 1 \ \text{c} \hline
\end{array}

and the compilation of it results in the following table,

[Table viewable in horizontal mode]

which is identical to the table in $(1)$. It is good to notice that backward slash needs to be escaped with an extra “\”, so that Javascript interpreter of a web browser does not dispose this necessary forward slash and the possible character following the slash.

Some improvements that could be done to the above code is to define a string variable for setting the indentation level for the generated $\LaTeX$ and separating the \end of the array as concatenation to the tbl.innerHTML string so that the logic which computes and “stringifies” the results into $\LaTeX$ syntax.

After this re-write, the code for creating the required $\LaTeX$ syntax becomes

const indnt = '    '; // Row indentation level

tbl.innerHTML = 
    '\\begin{array}{ | c | c | c | c | c | c | c | c | } \\hline' + '\n'
        + indnt
        + 'f(n) &'
        + ' 1 \\ \\text{s} &'
        + ' 1 \\ \\text{min} &'
        + ' 1 \\ \\text{h} &'
        + ' 1 \\ \\text{d} &'
        + ' 1 \\ \\text{m} &'
        + ' 1 \\ \\text{y} &'
        + ' 1 \\ \\text{c}'
        + ' \\\\ ' + '\\hline' + '\n';

tbl.innerHTML += '\\end{array}';

The changes do not change the rendered results table.

After this, the durations can be declared as an Javascript array by declaring

const durations = [
    /* second  */ 1000,
    /* minute  */  60 * 1000,
    /* hour    */  60 * (60 * 1000),
    /* day     */  24 * (60 * (60 * 1000)),
    /* month   */  30 * (24 * (60 * (60 * 1000))),
    /* year    */  12 * (30 * (24 * (60 * (60 * 1000)))),
    /* century */ 100 * (12 * (30 * (24 * (60 * (60 * 1000)))))
];

and declaring the predefined functions as an array of functors

const f = {
    'n'             : (t) => t,
    '\\dfrac{1}{2}' : (t) => 0.5 * t
};

Where the key of a function is the function’s symbolical algebraic definition. This keying scheme is okay, because after the declaration no keys have to be typed manually because the functions of ‘f’ are referenced in the functor array only indirectly via iterator by writing

for (const [name, f] of Object.entries(functions)) {
    tbl.innerHTML += indnt + name;

    for (const t of durations) {
        // ...
    }

    tbl.innerHTML += ' \\\\ ' + '\\hline' + ' ' + '\n';
}

where the comment “// ...” is replaced with line of code that concatenates computations in $\LaTeX$ formatted Javascript string to be rendered with a $\LaTeX$ engine. This line could be written, for example, as

tbl.innerHTML += ' & ' + '\\small{'
    + Number.parseFloat(f(t)).toExponential(2)
+ '}';

Using this line the whole code written so far leads to

tbl = document.getElementById("tbl");

const durations = [
    /* second  */ 1000,
    /* minute  */  60 * 1000,
    /* hour    */  60 * (60 * 1000),
    /* day     */  24 * (60 * (60 * 1000)),
    /* month   */  30 * (24 * (60 * (60 * 1000))),
    /* year    */  12 * (30 * (24 * (60 * (60 * 1000)))),
    /* century */ 100 * (12 * (30 * (24 * (60 * (60 * 1000)))))
];

const f = {
    'n'             : (t) => t,
    '\\frac{1}{2}n' : (t) => 0.5 * t
};

tbl.innerHTML = 
    '\\begin{array}{ | c | c | c | c | c | c | c | c | } \\hline'
        + '\n'
        + indnt // Row indentation
        + 'f(n) &'
        + ' 1 \\ \\text{s} &'
        + ' 1 \\ \\text{min} &'
        + ' 1 \\ \\text{h} &'
        + ' 1 \\ \\text{d} &'
        + ' 1 \\ \\text{m} &'
        + ' 1 \\ \\text{y} &'
        + ' 1 \\ \\text{c}'
        + ' \\\\ ' + '\\hline' + '\n';

for (const [name, f] of Object.entries(functions)) {
    tbl.innerHTML += indnt + name;

    for (const t of durations) {
        tbl.innerHTML += ' & ' + '\\small{'
            + Number.parseFloat(f(t)).toExponential(2)
        + '}';
    }

    tbl.innerHTML += ' \\\\ ' + '\\hline' + ' ' + '\n';
}

tbl.innerHTML += '\\end{array}'

which is then rendered as

[Table viewable in horizontal mode]

as was expected. Note that more functions could then be added to f object defined at line 13 of the code above to add more rows to the table.