Edit: Xcode Version 12.5 beta (12E5220o), the Playground project is created with iOS template. Not the iPad Playground app!
This
extension Sequence where Element: Comparable {
public var runLength: [(element: Element, count: Int)] { ... }
}
when called with [Int], the tuple elements has names, with String, tuple elements have no names.
When I reduce down, the same call signature works for both String and [Int]: both have tuple elementals names.
I've used (element: Element, count: Int) (with element name) everywhere (though I don't believe I need to do so) but still, same problem.
Here is my code:
// For use with Sequence.reduce(into:) to scan each element to keep count of each element
private struct RunLength<T: Comparable> {
private struct ElementCount {
let element: T
var count = 1
}
// keep track the count of each element in this array
private var elementCounts = [ElementCount]()
// scan each element, call this to count it
mutating func process(element: T) {
// element is a different value, so it's start of a new run
// or this is the very first run when elementCounts.isEmpty so on left side is nil
if elementCounts.last?.element != element {
elementCounts.append(ElementCount(element: element))
} else {
elementCounts[elementCounts.count - 1].count += 1
}
}
// the result as an array of tuples to avoid leeking out implementation type details
var result: [(element: T, count: Int)] {
elementCounts.map { (element: $0.element, count: $0.count) }
}
}
extension Sequence where Element: Comparable {
public var runLength: [(element: Element, count: Int)] {
reduce(into: RunLength()) { $0.process(element: $1) }
.result
}
}
// with array, the result tuple element is anotated with name
print([1, 1, 1, 1, 2, 2, 2, 3, 3, 1].runLength)
// prints out: [(element: 1, count: 4), (element: 2, count: 3), (element: 3, count: 2), (element: 1, count: 1)]
// with String, the result tuple element is not annotated with name
print("aaaabbbcca".runLength)
// prints out: [("a", 4), ("b", 3), ("c", 2), ("a", 1)]