apple / apple/swift-algorithms

Add capability to sort on a custom mapping (e.g., on a particular member)

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

Description

There seems to be [broad](https://forums.swift.org/t/sorting-collections-with-map-closures-and-sortdescriptors/16276) [appetite](https://twitter.com/bjhomer/status/1366461518435426304) for sorting on, say, surnames or ages for a collection of `Person` values. This has been made even more ergonomic now that key path literals can be used where a function takes a closure as an argument.

I'd propose, therefore, to add the following `sorted(on:by:)` and `sort(on:by:)` additions:

```swift
extension Sequence {
@inlinable
public func sorted(
on transform: (Self.Element) throws -> T,
by areInIncreasingOrder: (T, T) throws -> Bool
) rethrows -> [Element] {
try sorted {
try areInIncreasingOrder(transform($0), transform($1))
}
}

@inlinable
public func sorted(
on transform: (Self.Element) throws -> T
) rethrows -> [Element] {
try sorted { try transform($0) < transform($1) }
}
}

extension MutableCollection where Self: RandomAccessCollection {
@inlinable
public mutating func sort(
on transform: (Self.Element) throws -> T,
by areInIncreasingOrder: (T, T) throws -> Bool
) rethrows {
try sort {
try areInIncreasingOrder(transform($0), transform($1))
}
}

@inlinable
public mutating func sort(
on transform: (Self.Element) throws -> T
) rethrows {
try sort { try transform($0) < transform($1) }
}
}
```

The use site would look like the following:

```swift
struct Person {
var name: String
var age: Int
}

let persons = [
Person(name: "Alice", age: 56),
Person(name: "Bob", age: 34)
]

let x = persons.sorted(on: \.name, by: >)
let y = persons.sorted(on: \.age)
```

Any interest in such a change?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.