Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
fwgreen opened this issue Apr 1, 2023 · 0 comments
Labels
enhancement New feature or request

Comments

@fwgreen
Copy link

fwgreen commented Apr 1, 2023

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.

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:

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+-------+-------+-------+")
}
natecook1000 added a commit that referenced this issue May 9, 2023
Joining with a prefix and suffix is a relatively common operation that
isn't terribly simple to implement concisely. This adds that operation
for joining strings.

Related to #195.
@natecook1000 natecook1000 added the enhancement New feature or request label May 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants