How to "spread" a 2d array in table?

Hi,

I have a 2d array defined in a json file with following structure

[
    [
        "Date",
        "Tran Type",
        "Tran ID",
        "Withdrawals",
        "Deposits"
    ],
    [
        "01/05/2024",
        "TFR",
        "S81420904",
        "700.00",
        ""
    ],
    [
        "01/05/2024",
        "TFR",
        "S84554541",
        "",
        "1.01"
    ]
]

I am looking to format this as a table. The first row is the header and after that it’s data rows. The attempt I have made is as follows:

#let txn = json("data1.json")

#txn.at(0)

#let to_content(r) = [#r.at(0) #r.at(1) #r.at(2) #r.at(3) #r.at(4)]

#table(
  columns: 5,
  to_content(..txn)
)

Which obviously is not working. Is there a means to format the 2d array as a table directly?

Use array.flatten():

#let txn = json("data1.json")

#table(
  columns: 5,
  ..txn.flatten()
)
1 Like

Thanks! Its working fine.

Just a followup question about how flatten() work here. I can understand that the .. spread operator converts the resultent arraay into individual rows that can be used by #table . But I could not yet fully understand the flatten() operator. The table expects (in my faulty understanding) data in the form of a row, which is what each row of ..txn provides, what additional facility does flatten() provides?

The reference also do not shed much light into the implication of flatten()

Combine all nested arrays into a single flat one.

Thanks!

  • What does flatten do?
    flatten() converts a multi-dimensional array into a one-dimensional array. For example, in your case, txn is a 2D array (which means elements in array are 1D array) like:

    (
        (
            "Date",
            "Tran Type",
            "Tran ID",
            "Withdrawals",
            "Deposits"
        ),
        (
            "01/05/2024",
            "TFR",
            "S81420904",
            "700.00",
            ""
        ),
        (
            "01/05/2024",
            "TFR",
            "S84554541",
            "",
            "1.01"
        )
    )
    

    and txn.flatten() returns a 1D array like:

    (
        "Date",
        "Tran Type",
        "Tran ID",
        "Withdrawals",
        "Deposits",
        "01/05/2024",
        "TFR",
        "S81420904",
        "700.00",
        "",
        "01/05/2024",
        "TFR",
        "S84554541",
        "",
        "1.01",
    )
    
  • What should we provide to table ?
    The table does not treat cells from different columns differently, so you don’t need to use other functions (like your to_content) to construct a complete row. Instead, we should provide the table with individual cell content.

    Simply using ..array.flatten() works because the data you provide comes in groups of five, and the table is set to have five columns, so each group of data perfectly fills one row.

  • About .. operator
    Basically, you can think of the .. operator as removing the brackets from around the list. For example:

    #let txn = (
      (
        "Date",
        "Tran Type",
      ),
      (
        "01/05/2024",
        "TFR",
      ),
    )
    #table(columns: 2, ..txn)
    

    is equivalent to (simply replacing the variable):

    #table(columns: 2, ..(
      (
        "Date",
        "Tran Type",
      ),
      (
        "01/05/2024",
        "TFR",
      ),
    ))
    

    is equivalent to (spread array with ..)

    #table(
      columns: 2,
      (
        "Date",
        "Tran Type",
      ),
      (
        "01/05/2024",
        "TFR",
      ),
    )
    

    This won’t work because table does not accept array as row, (it receives str or content as individual cell, as we mentioned above), but with ..txn.flatten(), we will get:

    #table(
      columns: 2,
      "Date", "Tran Type",
      "01/05/2024", "TFR",
    )
    

    That’s exactly what we want.

2 Likes

Thanks for the helpful explanation! Couple of questions, if I may:

In ..array.flatten() in which order does the operations happen? ie does the flatten() happen first or does the .. spread happen first?

  1. If flatten() happen first, then how does the .. knows how to split the array into rows, because it will be just one big 1d array.
  2. If .. happen first then we have a collection of 1d arrays, and the flatten() operator do not have a multi-dimentional array to work with. In this case, will it just return a just a collection of content?

flatten() happens first.

.. DOES NOT split array. It just unpacks. table splits providing cells into rows based on columns argument.

1 Like

Thanks, that clarifies it!