apple / apple/swift-algorithms

Consider adding a function that creates a string representation of a collection similar to Scala's mkString

Open
#195 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Swift
Stars
6.3k
Forks
483
PR merge metrics
No merged PRs in 30d

Description

**Motivation:**
I wanted to pretty print a 2D array (a Sudoku board) and found mapping to string and using `joined(by:)` fell short of what I needed.
```Swift
let input = [
[5,3,0, 0,7,0, 0,0,0],
[6,0,0, 1,9,5, 0,0,0],
[0,9,8, 0,0,0, 0,6,0],

[8,0,0, 0,6,0, 0,0,3],
[4,0,0, 8,0,3, 0,0,1],
[7,0,0, 0,2,0, 0,0,6],

[0,6,0, 0,0,0, 2,8,0],
[0,0,0, 4,1,9, 0,0,5],
[0,0,0, 0,8,0, 0,7,9],
]
/*
+-------+-------+-------+
| 5 3 0 | 0 7 0 | 0 0 0 |
| 6 0 0 | 1 9 5 | 0 0 0 |
| 0 9 8 | 0 0 0 | 0 6 0 |
+-------+-------+-------+
| 8 0 0 | 0 6 0 | 0 0 3 |
| 4 0 0 | 8 0 3 | 0 0 1 |
| 7 0 0 | 0 2 0 | 0 0 6 |
+-------+-------+-------+
| 0 6 0 | 0 0 0 | 2 8 0 |
| 0 0 0 | 4 1 9 | 0 0 5 |
| 0 0 0 | 0 8 0 | 0 7 9 |
+-------+-------+-------+
*/
```
My current solution is to copy Scala's `mkString` but I wonder if there is a better (more general and performant) way:
```Swift
extension Collection {
func makeString(_ separator: String) -> String { makeString("", separator, "") }

func makeString(_ prefix: String, _ separator: String, _ suffix: String) -> String {
if isEmpty {
return prefix + suffix
} else {
return addString("", prefix, separator, suffix)
}
}

private func addString(_ string: String, _ prefix: String, _ separator: String, _ suffix: String) -> String {
var string = string
if prefix.count != 0 { string.append(contentsOf: prefix) }
var it = makeIterator()
if let start = it.next() {
string.append(contentsOf: "\(start)")
while let rest = it.next() {
string.append(contentsOf: separator)
string.append(contentsOf: "\(rest)")
}
}
if suffix.count != 0 { string.append(contentsOf: suffix) }
return string
}
}
//This allows for something close to what is possible in Scala
func prettyString(_ sudoku: [[Int]]) -> String {
sudoku.chunks(ofCount: 3).map { bigChunck in
bigChunck.map { row in
row.chunks(ofCount: 3).map { smallChunk in
smallChunk.makeString(" ", " ", " ")
}.makeString("|", "|", "|")
}.makeString("\n")
}.makeString("+-------+-------+-------+\n", "\n+-------+-------+-------+\n", "\n+-------+-------+-------+")
}
```

Contributor guide

Open the contributing guide

Research direction

The issue names no repository files or tests. Start by reviewing the existing Collection string APIs, especially joined(by:), and the proposed makeString examples; clarify the desired nested-collection and empty-collection behavior before locating the appropriate implementation and test targets. Done means an agreed API with coverage for the demonstrated formatting cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
developer-experience
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.