mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
@@ -473,260 +473,3 @@ extension MutableCollection where Self : RandomAccessCollection {
|
||||
shuffle(using: &Random.default)
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// sorted()/sort()
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
extension Sequence where Element : Comparable {
|
||||
/// Returns the elements of the sequence, sorted.
|
||||
///
|
||||
/// You can sort any sequence of elements that conform to the `Comparable`
|
||||
/// protocol by calling this method. Elements are sorted in ascending order.
|
||||
///
|
||||
/// The sorting algorithm is not stable. A nonstable sort may change the
|
||||
/// relative order of elements that compare equal.
|
||||
///
|
||||
/// Here's an example of sorting a list of students' names. Strings in Swift
|
||||
/// conform to the `Comparable` protocol, so the names are sorted in
|
||||
/// ascending order according to the less-than operator (`<`).
|
||||
///
|
||||
/// let students: Set = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
|
||||
/// let sortedStudents = students.sorted()
|
||||
/// print(sortedStudents)
|
||||
/// // Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"
|
||||
///
|
||||
/// To sort the elements of your sequence in descending order, pass the
|
||||
/// greater-than operator (`>`) to the `sorted(by:)` method.
|
||||
///
|
||||
/// let descendingStudents = students.sorted(by: >)
|
||||
/// print(descendingStudents)
|
||||
/// // Prints "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"
|
||||
///
|
||||
/// - Returns: A sorted array of the sequence's elements.
|
||||
@inlinable
|
||||
public func sorted() -> [Element] {
|
||||
var result = ContiguousArray(self)
|
||||
result.sort()
|
||||
return Array(result)
|
||||
}
|
||||
}
|
||||
|
||||
extension Sequence {
|
||||
/// Returns the elements of the sequence, sorted using the given predicate as
|
||||
/// the comparison between elements.
|
||||
///
|
||||
/// When you want to sort a sequence of elements that don't conform to the
|
||||
/// `Comparable` protocol, pass a predicate to this method that returns
|
||||
/// `true` when the first element passed should be ordered before the
|
||||
/// second. The elements of the resulting array are ordered according to the
|
||||
/// given predicate.
|
||||
///
|
||||
/// The predicate must be a *strict weak ordering* over the elements. That
|
||||
/// is, for any elements `a`, `b`, and `c`, the following conditions must
|
||||
/// hold:
|
||||
///
|
||||
/// - `areInIncreasingOrder(a, a)` is always `false`. (Irreflexivity)
|
||||
/// - If `areInIncreasingOrder(a, b)` and `areInIncreasingOrder(b, c)` are
|
||||
/// both `true`, then `areInIncreasingOrder(a, c)` is also `true`.
|
||||
/// (Transitive comparability)
|
||||
/// - Two elements are *incomparable* if neither is ordered before the other
|
||||
/// according to the predicate. If `a` and `b` are incomparable, and `b`
|
||||
/// and `c` are incomparable, then `a` and `c` are also incomparable.
|
||||
/// (Transitive incomparability)
|
||||
///
|
||||
/// The sorting algorithm is not stable. A nonstable sort may change the
|
||||
/// relative order of elements for which `areInIncreasingOrder` does not
|
||||
/// establish an order.
|
||||
///
|
||||
/// In the following example, the predicate provides an ordering for an array
|
||||
/// of a custom `HTTPResponse` type. The predicate orders errors before
|
||||
/// successes and sorts the error responses by their error code.
|
||||
///
|
||||
/// enum HTTPResponse {
|
||||
/// case ok
|
||||
/// case error(Int)
|
||||
/// }
|
||||
///
|
||||
/// let responses: [HTTPResponse] = [.error(500), .ok, .ok, .error(404), .error(403)]
|
||||
/// let sortedResponses = responses.sorted {
|
||||
/// switch ($0, $1) {
|
||||
/// // Order errors by code
|
||||
/// case let (.error(aCode), .error(bCode)):
|
||||
/// return aCode < bCode
|
||||
///
|
||||
/// // All successes are equivalent, so none is before any other
|
||||
/// case (.ok, .ok): return false
|
||||
///
|
||||
/// // Order errors before successes
|
||||
/// case (.error, .ok): return true
|
||||
/// case (.ok, .error): return false
|
||||
/// }
|
||||
/// }
|
||||
/// print(sortedResponses)
|
||||
/// // Prints "[.error(403), .error(404), .error(500), .ok, .ok]"
|
||||
///
|
||||
/// You also use this method to sort elements that conform to the
|
||||
/// `Comparable` protocol in descending order. To sort your sequence in
|
||||
/// descending order, pass the greater-than operator (`>`) as the
|
||||
/// `areInIncreasingOrder` parameter.
|
||||
///
|
||||
/// let students: Set = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
|
||||
/// let descendingStudents = students.sorted(by: >)
|
||||
/// print(descendingStudents)
|
||||
/// // Prints "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"
|
||||
///
|
||||
/// Calling the related `sorted()` method is equivalent to calling this
|
||||
/// method and passing the less-than operator (`<`) as the predicate.
|
||||
///
|
||||
/// print(students.sorted())
|
||||
/// // Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"
|
||||
/// print(students.sorted(by: <))
|
||||
/// // Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"
|
||||
///
|
||||
/// - Parameter areInIncreasingOrder: A predicate that returns `true` if its
|
||||
/// first argument should be ordered before its second argument;
|
||||
/// otherwise, `false`.
|
||||
/// - Returns: A sorted array of the sequence's elements.
|
||||
@inlinable
|
||||
public func sorted(
|
||||
by areInIncreasingOrder:
|
||||
(Element, Element) throws -> Bool
|
||||
) rethrows -> [Element] {
|
||||
var result = ContiguousArray(self)
|
||||
try result.sort(by: areInIncreasingOrder)
|
||||
return Array(result)
|
||||
}
|
||||
}
|
||||
|
||||
extension MutableCollection
|
||||
where
|
||||
Self : RandomAccessCollection, Element : Comparable {
|
||||
|
||||
/// Sorts the collection in place.
|
||||
///
|
||||
/// You can sort any mutable collection of elements that conform to the
|
||||
/// `Comparable` protocol by calling this method. Elements are sorted in
|
||||
/// ascending order.
|
||||
///
|
||||
/// The sorting algorithm is not stable. A nonstable sort may change the
|
||||
/// relative order of elements that compare equal.
|
||||
///
|
||||
/// Here's an example of sorting a list of students' names. Strings in Swift
|
||||
/// conform to the `Comparable` protocol, so the names are sorted in
|
||||
/// ascending order according to the less-than operator (`<`).
|
||||
///
|
||||
/// var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
|
||||
/// students.sort()
|
||||
/// print(students)
|
||||
/// // Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"
|
||||
///
|
||||
/// To sort the elements of your collection in descending order, pass the
|
||||
/// greater-than operator (`>`) to the `sort(by:)` method.
|
||||
///
|
||||
/// students.sort(by: >)
|
||||
/// print(students)
|
||||
/// // Prints "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"
|
||||
@inlinable
|
||||
public mutating func sort() {
|
||||
let didSortUnsafeBuffer: Void? =
|
||||
_withUnsafeMutableBufferPointerIfSupported {
|
||||
(bufferPointer) -> Void in
|
||||
bufferPointer.sort()
|
||||
return ()
|
||||
}
|
||||
if didSortUnsafeBuffer == nil {
|
||||
_introSort(&self, subRange: startIndex..<endIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension MutableCollection where Self : RandomAccessCollection {
|
||||
/// Sorts the collection in place, using the given predicate as the
|
||||
/// comparison between elements.
|
||||
///
|
||||
/// When you want to sort a collection of elements that doesn't conform to
|
||||
/// the `Comparable` protocol, pass a closure to this method that returns
|
||||
/// `true` when the first element passed should be ordered before the
|
||||
/// second.
|
||||
///
|
||||
/// The predicate must be a *strict weak ordering* over the elements. That
|
||||
/// is, for any elements `a`, `b`, and `c`, the following conditions must
|
||||
/// hold:
|
||||
///
|
||||
/// - `areInIncreasingOrder(a, a)` is always `false`. (Irreflexivity)
|
||||
/// - If `areInIncreasingOrder(a, b)` and `areInIncreasingOrder(b, c)` are
|
||||
/// both `true`, then `areInIncreasingOrder(a, c)` is also `true`.
|
||||
/// (Transitive comparability)
|
||||
/// - Two elements are *incomparable* if neither is ordered before the other
|
||||
/// according to the predicate. If `a` and `b` are incomparable, and `b`
|
||||
/// and `c` are incomparable, then `a` and `c` are also incomparable.
|
||||
/// (Transitive incomparability)
|
||||
///
|
||||
/// The sorting algorithm is not stable. A nonstable sort may change the
|
||||
/// relative order of elements for which `areInIncreasingOrder` does not
|
||||
/// establish an order.
|
||||
///
|
||||
/// In the following example, the closure provides an ordering for an array
|
||||
/// of a custom enumeration that describes an HTTP response. The predicate
|
||||
/// orders errors before successes and sorts the error responses by their
|
||||
/// error code.
|
||||
///
|
||||
/// enum HTTPResponse {
|
||||
/// case ok
|
||||
/// case error(Int)
|
||||
/// }
|
||||
///
|
||||
/// var responses: [HTTPResponse] = [.error(500), .ok, .ok, .error(404), .error(403)]
|
||||
/// responses.sort {
|
||||
/// switch ($0, $1) {
|
||||
/// // Order errors by code
|
||||
/// case let (.error(aCode), .error(bCode)):
|
||||
/// return aCode < bCode
|
||||
///
|
||||
/// // All successes are equivalent, so none is before any other
|
||||
/// case (.ok, .ok): return false
|
||||
///
|
||||
/// // Order errors before successes
|
||||
/// case (.error, .ok): return true
|
||||
/// case (.ok, .error): return false
|
||||
/// }
|
||||
/// }
|
||||
/// print(responses)
|
||||
/// // Prints "[.error(403), .error(404), .error(500), .ok, .ok]"
|
||||
///
|
||||
/// Alternatively, use this method to sort a collection of elements that do
|
||||
/// conform to `Comparable` when you want the sort to be descending instead
|
||||
/// of ascending. Pass the greater-than operator (`>`) operator as the
|
||||
/// predicate.
|
||||
///
|
||||
/// var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
|
||||
/// students.sort(by: >)
|
||||
/// print(students)
|
||||
/// // Prints "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"
|
||||
///
|
||||
/// - Parameter areInIncreasingOrder: A predicate that returns `true` if its
|
||||
/// first argument should be ordered before its second argument;
|
||||
/// otherwise, `false`. If `areInIncreasingOrder` throws an error during
|
||||
/// the sort, the elements may be in a different order, but none will be
|
||||
/// lost.
|
||||
@inlinable
|
||||
public mutating func sort(
|
||||
by areInIncreasingOrder:
|
||||
(Element, Element) throws -> Bool
|
||||
) rethrows {
|
||||
|
||||
let didSortUnsafeBuffer: Void? =
|
||||
try _withUnsafeMutableBufferPointerIfSupported {
|
||||
(bufferPointer) -> Void in
|
||||
try bufferPointer.sort(by: areInIncreasingOrder)
|
||||
return ()
|
||||
}
|
||||
if didSortUnsafeBuffer == nil {
|
||||
try _introSort(
|
||||
&self,
|
||||
subRange: startIndex..<endIndex,
|
||||
by: areInIncreasingOrder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user