swift-collections
swift-collections copied to clipboard
Adding `Self`-returning overload of `sorted()` for `OrderedDictionary` and `OrderedSet`?
There are mutating methods on OrderedDictionary and OrderedSet that sort them in-place, so sorting is well-defined on these types. But there are no copy-returning sorted() variants for these types.
The question is: Is there a specific reason why these are not included so far? I realize that adding this would be a source-breaking change for OrderedSet, so I guess the bar for including this is very high by now.
FYI, I asked on the Swift Forums about this (but I was confused a bit and didn’t see the Sequence.sorted() version): https://forums.swift.org/t/why-is-there-a-sort-but-no-sorted-method-on-ordereddictionary-and-orderedset/79978/2
A little more info:
OrderedSet uses the default implementation from Sequence, which returns an Array instead of an OrderedSet, which is unfortunate if you want to keep working with an OrderedSet:
let set: OrderedSet = [3, 2, 1]
print(type(of: set.sorted())) // Array<Int>
let sortedSet = OrderedSet(set.sorted()) // Possible, but not ideal 😕
And OrderedDictionary sees the default implementation from Sequence, but the compiler rightly errors out:
let dict: OrderedDictionary = [1: "one", 2: "two", 3: "three"]
print(type(of: dict.sorted())) // error: Type 'OrderedDictionary<Int, String>.Element' (aka '(key: Int, value: String)') cannot conform to 'Comparable'
Adding Self-returning variants and thereby shadowing the Sequence implementations is very easy, of course, e.g.:
extension OrderedSet {
func sorted() -> Self where Element: Comparable {
var copy = self
copy.sort()
return copy
}
}
extension OrderedDictionary {
func sorted() -> Self where Key: Comparable {
var copy = self
copy.sort()
return copy
}
}
…which results in this:
let dict: OrderedDictionary = [1: "one", 2: "two", 3: "three"]
print(type(of: dict.sorted())) // OrderedDictionary<Int, String>
let set: OrderedSet = [3, 2, 1]
print(type(of: set.sorted())) // OrderedSet<Int>
…which is what I personally would have expected 🙂