I think it may be useful to have real-world statistics on how often <
, >
, and other more complicated sorting constructs ( localizedCaseInsensitiveCompare == .orderedAscending
is my go-to "complex" example) actually get used in the wild.
In the Swift Source Compatibility Suite
I identified 243 instances of sort
/ sorted
in the swift-source-compat-suite. Of these 243, 80% (194
) used <
either as their comparator or as the primary operation in their comparator closure. 12% (30
) used >
. The remaining 8% of sorts (19
) mostly checked for == .orderedAscending
. Only 1-2% of the sorts in the compatibility suite used some comparison operator other than <
, >
or == .orderedAscending
.
54% (132
) of the sorts provided a custom areInIncreasingOrder
closure. Of those 132 closures, 53% (71
) took the form { $0.someProperty < $1.someProperty }
and 10% (14) took the form { $0.someProperty > $1.someProperty }
.
Potential Impact of this Proposal
In all, 30% of the sorts I identified in the Source Compatibility Suite took the form { $0.someProperty < $1.someProperty }
. Over half of the sorts that provided a custom areInIncreasingOrder
closure took that form as well.
With these overloads below, 30% of all sorts in the compatibility suite (and the majority of sorts that provided a areInIncreasingOrder
closure at all) could be improved from sorted { $0.someProperty < $1.someProperty }
to sorted { $0.someProperty }
.
5% could be improved from sorted { $0.someProperty > $1.someProperty }
to sorted(using: { $0.someProperty }, by: >)
extension Sequence {
func sorted<Value>(using transform: (Element) -> Value, by: (Value, Value) -> Bool) -> [Element] {
...
}
func sorted<Value: Comparable>(using transform: (Element) -> Value) -> [Element] {
return self.sorted(using: transform, by: <)
}
}
// + corresponding `sort` overloads
My raw notes:
.sorted(): 62
.sort(): 7
.sorted(by: <)
: 30
.sort(by: <)
: 0
.sorted(by: >)
: 12
.sort(by: >)
: 0
.sorted {
total: 87
block with <: 67
block with >: 8
{ $0.someProperty < $1.someProperty }
: 48
{ $0.someProperty > $1.someProperty }
: 6
.sorted(by: {
total: 36
block with <: 24
block with >: 8
{ $0.someProperty < $1.someProperty }
: 19
{ $0.someProperty > $1.someProperty }
: 6
.sort {
total: 8
block with <: 3
block with >: 2
{ $0.someProperty < $1.someProperty }
: 3
{ $0.someProperty > $1.someProperty }
: 2
.sort(by: {
total: 1
block with <: 1
block with >: 0
{ $0.someProperty < $1.someProperty }
: 1
{ $0.someProperty > $1.someProperty }
: 0