Last active
March 23, 2025 14:42
-
-
Save Mahoney/9bff469a31f4e45cf10682fc4c5e213a to your computer and use it in GitHub Desktop.
Rendering a Markdown Table in Kotlin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| fun renderMarkdownTable( | |
| header: List<String>, | |
| rows: List<List<Any?>> | |
| ): String { | |
| val columnsAreNumeric: List<Boolean> = rows | |
| .map { row -> row.map { cell -> cell == null || cell is Number } } | |
| .reduce { areNumbersSoFar, row -> | |
| areNumbersSoFar.mapIndexed { index, isNumberSoFar -> | |
| isNumberSoFar && row[index] | |
| } | |
| } | |
| val formattedRows: List<List<String>> = rows | |
| .map { row -> | |
| row.mapIndexed { index, cell -> | |
| val isNumeric = columnsAreNumeric[index] | |
| if (isNumeric) { | |
| cell?.formatAsNumber() | |
| } else { | |
| cell?.toString() | |
| } ?: "" | |
| } | |
| } | |
| val maxSizes: List<Int> = (listOf(header) + formattedRows) | |
| .map { row -> row.map { cell -> cell.length } } | |
| .reduce { maxSizesSoFar, row -> | |
| maxSizesSoFar.mapIndexed { index, maxSizeSoFar -> | |
| maxOf(maxSizeSoFar, row[index]) | |
| } | |
| } | |
| val headerLine: List<String> = header | |
| .mapIndexed { index, cell -> | |
| val padding = maxSizes[index] | |
| cell.padEnd(padding) | |
| } | |
| val horizontalLine: List<String> = List(header.size) { index -> | |
| val padding = maxSizes[index] | |
| val isNumeric = columnsAreNumeric[index] | |
| val content = if (isNumeric) "---:" else "---" | |
| content.padStart(padding, '-') | |
| } | |
| val rowLines: List<List<String>> = formattedRows | |
| .map { row -> | |
| row.mapIndexed { index, cell -> | |
| val padding = maxSizes[index] | |
| val isNumeric = columnsAreNumeric[index] | |
| if (isNumeric) { | |
| cell.padStart(padding) | |
| } else { | |
| cell.padEnd(padding) | |
| } | |
| } | |
| } | |
| return (listOf(headerLine, horizontalLine) + rowLines).joinToString("\n") { | |
| it.joinToString(prefix = "| ", separator = " | ", postfix = " |") | |
| } | |
| } | |
| fun Any.formatAsNumber(): String = NumberFormat.getInstance().format(this) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment