# Table style print for 2D Array, Dictionary and Tuples

**URL:** <https://forums.swift.org/t/table-style-print-for-2d-array-dictionary-and-tuples/35121>\
**Category:** Pitches\
**Tags:** stdlib\
**Created:** [April 5, 2020, 5:04pm UTC](https://forums.swift.org/t/table-style-print-for-2d-array-dictionary-and-tuples/35121 "2020-04-05T17:04:05Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![ShawnBaek](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/shawnbaek/32/11141_2.png) [@ShawnBaek](https://forums.swift.org/u/ShawnBaek)\
**Post date:** [April 5, 2020, 5:04pm UTC](https://forums.swift.org/t/table-style-print-for-2d-array-dictionary-and-tuples/35121/1 "2020-04-05T17:04:06Z")

</div>

I suggest table-style printing for 2D arrays, dictionaries, and tuples. Inspired from [Javascript console.table](https://developer.mozilla.org/en-US/docs/Web/API/Console/table)

The **stdlib** print doesn't support table-style output. So It is hard to check the data in the 2D array.

Here is my suggestion. I made a sample project called [Table](https://github.com/ShawnBaek/Table).

**1D Array with Header**

```swift
print(
    table: ["Good", "Very Good", "Happy", "Cool!"], 
    header: ["Wed", "Thu", "Fri", "Sat"]
)

```

Output:

```swift
+----+---------+-----+-----+
|Wed |Thu |Fri |Sat |
+----+---------+-----+-----+
|Good|Very Good|Happy|Cool!|
+----+---------+-----+-----+

```

**2D Array but the length of data is not equal.**

```swift
print(
    table: [["1", "b2"], 
    ["Hellow", "Great!"], 
    ["sdjfklsjdfklsadf", "dsf", "1"]]
)

```

OUtput:

```swift
+----------------+------+-+
|1 |b2 | |
+----------------+------+-+
|Hellow |Great!| |
+----------------+------+-+
|sdjfklsjdfklsadf|dsf |1|
+----------------+------+-+

```

**Dictionary**

```swift
print(
    table: [
    "1": 1, 
    2: "Hellow?", 
    1.2: 0, 
    "I'm Table": [1, 2, 3, 2, 1]
    ], 
    header: ["key", "value"]
)

```

Output

```swift
+---------+---------------+
|key |value |
+---------+---------------+
|2 |Hellow? |
+---------+---------------+
|I'm Table|[1, 2, 3, 2, 1]|
+---------+---------------+
|1.2 |0 |
+---------+---------------+
|1 |1 |
+---------+---------------+

```

**Implementation**

1. Define the print function.

```swift
public enum TableSpacing {
    case fillProportionally
    case fillEqually
}
/// - Parameters:
/// - table: Zero or more items to print.
/// - header: A string to print header on table.
/// - terminator: A string to print end of function.
/// - distribution: A spacing for item
@discardableResult public func print(
    table data: Any,
    header: [String]? = nil,
    distribution: TableSpacing = .fillProportionally,
    terminator: String = ""
) -> String

```

1. Check the table type

```swift
let mirrorObj = Mirror(reflecting: data)

if mirrorObj.subjectType == [String].self {
}
else if mirrorObj.subjectType == [Int].self {
}
else if else if mirrorObj.subjectType == [AnyHashable: Any].self {
}
...

```

1. Helper functions

- 3.1 Horizontal Line  
Use for drawing the horizontal line on Table

```swift
@discardableResult private func horizontal(
    numberOfItems: Int,
    keyWidth: Int,
    valueWidth: Int,
    distribution: TableSpacing
) -> String

```

- 3.2 Table Infomation  
Calculating the spaces between the data

```swift
private func tableInfo(data: [AnyHashable: Any]) -> (
    numberOfItem: Int,
    maxKeyWidth: Int,
    maxValueWidth: Int,
    widthInfo: [String: Int]
    )

private func tableInfo<Item: LosslessStringConvertible>(data: [Item]) -> (
    numberOfItem: Int,
    maxWidth: Int,
    widthInfo: [Int: Int]
    )

private func tableInfo<Item: LosslessStringConvertible>(data: [[Item]]) -> (
    numberOfItem: Int,
    maxWidth: Int,
    widthInfo: [Int: Int]
    )

```

**Unit Test**

```swift
func test_1DArray_Of_String_with_header() {
        let output = print(
            table: ["Good", "Very Good", "Happy", "Cool!"],
            header: ["Wed", "Thu", "Fri", "Sat"]
        )
        let expected = """
            +----+---------+-----+-----+
            |Wed |Thu |Fri |Sat |
            +----+---------+-----+-----+
            |Good|Very Good|Happy|Cool!|
            +----+---------+-----+-----+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_1DArray_Of_Int() {
        let output = print(table: [2, 94231, 241245125125])
        let expected = """
            +-+-----+------------+
            |2|94231|241245125125|
            +-+-----+------------+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_1DArray_Of_Double() {
        let output = print(table: [2.0, 931, 214.24124])
        let expected = """
            +---+-----+---------+
            |2.0|931.0|214.24124|
            +---+-----+---------+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_2DArray_Of_String() {
        let output = print(
            table: [["1", "HELLOW"], ["2", "WOLLEH"]],
            header: ["Index", "Words"]
        )
        let expected = """
            +-----+------+
            |Index|Words |
            +-----+------+
            |1 |HELLOW|
            +-----+------+
            |2 |WOLLEH|
            +-----+------+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_2DArray_Of_String_With_Different_Columns() {
        let output = print(
            table: [["1", "b2"], ["Hellow", "Great!"], ["sdjfklsjdfklsadf", "dsf", "1"]],
            header: ["1", "2", "3"]
        )
        let expected = """
            +----------------+------+-+
            |1 |2 |3|
            +----------------+------+-+
            |1 |b2 | |
            +----------------+------+-+
            |Hellow |Great!| |
            +----------------+------+-+
            |sdjfklsjdfklsadf|dsf |1|
            +----------------+------+-+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_2DArray_Of_Int_With_Different_Columns() {
        let output = print(table: [[1, 2, 3], [4, 5, 6], [7, 8, 9, 10]])
        let expected = """
            +-+-+-+--+
            |1|2|3| |
            +-+-+-+--+
            |4|5|6| |
            +-+-+-+--+
            |7|8|9|10|
            +-+-+-+--+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_fillEqually_for_1DArray_Of_String_with_header() {
        let output = print(
            table: ["Good", "Very Good", "Happy", "Cool!"],
            header: ["Wed", "Thu", "Fri", "Sat"],
            distribution: .fillEqually
        )
        let expected = """
            +---------+---------+---------+---------+
            |Wed |Thu |Fri |Sat |
            +---------+---------+---------+---------+
            |Good |Very Good|Happy |Cool! |
            +---------+---------+---------+---------+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_fillEqually_for_1DArray_Of_Int() {
        let output = print(
            table: [2, 94231, 241245125125],
            distribution: .fillEqually
        )
        let expected = """
            +------------+------------+------------+
            |2 |94231 |241245125125|
            +------------+------------+------------+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_fillEqually_for_1DArray_Of_Double() {
        let output = print(
            table: [2.0, 931, 214.24124],
            distribution: .fillEqually
        )
        let expected = """
            +---------+---------+---------+
            |2.0 |931.0 |214.24124|
            +---------+---------+---------+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_fillEqually_for_2DArray_Of_String() {
        let output = print(
            table: [["1", "HELLOW"], ["2", "WOLLEH"]],
            header: ["Index", "Words"],
            distribution: .fillEqually
        )
        let expected = """
            +------+------+
            |Index |Words |
            +------+------+
            |1 |HELLOW|
            +------+------+
            |2 |WOLLEH|
            +------+------+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_fillEqually_for_2DArray_Of_String_With_Different_Columns() {
        let output = print(
            table: [["1", "b2"], ["Hellow", "Great!"], ["sdjfklsjdfklsadf", "dsf", "1"]],
            header: ["1", "2", "3"],
            distribution: .fillEqually
        )
        let expected = """
            +----------------+----------------+----------------+
            |1 |2 |3 |
            +----------------+----------------+----------------+
            |1 |b2 | |
            +----------------+----------------+----------------+
            |Hellow |Great! | |
            +----------------+----------------+----------------+
            |sdjfklsjdfklsadf|dsf |1 |
            +----------------+----------------+----------------+
            """
        XCTAssertEqual(output, expected)
    }
    
    func test_fillEqually_for_2DArray_Of_Int_With_Different_Columns() {
        let output = print(
            table: [[1, 2, 3], [4, 5, 6], [7, 8, 9, 10]],
            distribution: .fillEqually
        )
        let expected = """
            +--+--+--+--+
            |1 |2 |3 | |
            +--+--+--+--+
            |4 |5 |6 | |
            +--+--+--+--+
            |7 |8 |9 |10|
            +--+--+--+--+
            """
        XCTAssertEqual(output, expected)
    }

```

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [April 5, 2020, 8:23pm UTC](https://forums.swift.org/t/table-style-print-for-2d-array-dictionary-and-tuples/35121/2 "2020-04-05T20:23:25Z")

</div>

I like it. You may also want to participate in [this related topic](https://forums.swift.org/t/a-better-data-pretty-printer/34914).

---

<div class="post-metadata">

**Author:** ![SDGGiesbrecht](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sdggiesbrecht/32/4768_2.png) [@SDGGiesbrecht](https://forums.swift.org/u/SDGGiesbrecht)\
**Post date:** [April 6, 2020, 2:28am UTC](https://forums.swift.org/t/table-style-print-for-2d-array-dictionary-and-tuples/35121/3 "2020-04-06T02:28:24Z")

</div>

Text really isn’t suited for faking layout:

```swift
+------+------------+
|Hebrew|Arabic |
+------+------------+
|שלום |السلام عليكم|
+------+------------+

```

😱

But if you are a stickler for old‐fashioned hacks, then [the actual box‐drawing characters](https://www.unicode.org/charts/PDF/U2500.pdf) will look nicer with any text that _does_ obey their bounds.

---

<div class="post-metadata">

**Author:** ![ShawnBaek](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/shawnbaek/32/11141_2.png) [@ShawnBaek](https://forums.swift.org/u/ShawnBaek)\
**Post date:** [April 6, 2020, 1:50pm UTC](https://forums.swift.org/t/table-style-print-for-2d-array-dictionary-and-tuples/35121/4 "2020-04-06T13:50:30Z")

</div>

Thank you 😅

I'll fix it.

---

<div class="post-metadata">

**Author:** ![ShawnBaek](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/shawnbaek/32/11141_2.png) [@ShawnBaek](https://forums.swift.org/u/ShawnBaek)\
**Post date:** [April 9, 2020, 2:41pm UTC](https://forums.swift.org/t/table-style-print-for-2d-array-dictionary-and-tuples/35121/5 "2020-04-09T14:41:57Z")

</div>

Thank you 😃
