mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[stdlib] Implement sequence/collection methods for searching from the end (#13337)
This implements the new last(where:), and lastIndex(of/where:) methods as extensions on `BidirectionalCollection`, which partially implements SE-204. The protocol requirements for `Sequence` and `Collection` as described in the proposal need to wait until there's a solution for picking up the specialized versions in types that conditionally conform to `BidirectionalCollection`.
This commit is contained in:
@@ -122,6 +122,97 @@ extension Collection {
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// lastIndex(of:)/lastIndex(where:)
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
extension BidirectionalCollection {
|
||||
/// Returns the last element of the sequence that satisfies the given
|
||||
/// predicate.
|
||||
///
|
||||
/// This example uses the `last(where:)` method to find the last
|
||||
/// negative number in an array of integers:
|
||||
///
|
||||
/// let numbers = [3, 7, 4, -2, 9, -6, 10, 1]
|
||||
/// if let lastNegative = numbers.last(where: { $0 < 0 }) {
|
||||
/// print("The last negative number is \(firstNegative).")
|
||||
/// }
|
||||
/// // Prints "The last negative number is -6."
|
||||
///
|
||||
/// - Parameter predicate: A closure that takes an element of the sequence as
|
||||
/// its argument and returns a Boolean value indicating whether the
|
||||
/// element is a match.
|
||||
/// - Returns: The last element of the sequence that satisfies `predicate`,
|
||||
/// or `nil` if there is no element that satisfies `predicate`.
|
||||
@inlinable
|
||||
public func last(
|
||||
where predicate: (Element) throws -> Bool
|
||||
) rethrows -> Element? {
|
||||
return try lastIndex(where: predicate).map { self[$0] }
|
||||
}
|
||||
|
||||
/// Returns the index of the last element in the collection that matches the
|
||||
/// given predicate.
|
||||
///
|
||||
/// You can use the predicate to find an element of a type that doesn't
|
||||
/// conform to the `Equatable` protocol or to find an element that matches
|
||||
/// particular criteria. This example finds the index of the last name that
|
||||
/// begins with the letter "A":
|
||||
///
|
||||
/// let students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
|
||||
/// if let i = students.lastIndex(where: { $0.hasPrefix("A") }) {
|
||||
/// print("\(students[i]) starts with 'A'!")
|
||||
/// }
|
||||
/// // Prints "Akosua starts with 'A'!"
|
||||
///
|
||||
/// - Parameter predicate: A closure that takes an element as its argument
|
||||
/// and returns a Boolean value that indicates whether the passed element
|
||||
/// represents a match.
|
||||
/// - Returns: The index of the last element in the collection that matches
|
||||
/// `predicate`, or `nil` if no elements match.
|
||||
@inlinable
|
||||
public func lastIndex(
|
||||
where predicate: (Element) throws -> Bool
|
||||
) rethrows -> Index? {
|
||||
var i = endIndex
|
||||
while i != startIndex {
|
||||
formIndex(before: &i)
|
||||
if try predicate(self[i]) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
extension BidirectionalCollection where Element : Equatable {
|
||||
/// Returns the last index where the specified value appears in the
|
||||
/// collection.
|
||||
///
|
||||
/// After using `lastIndex(of:)` to find the position of the last instance of
|
||||
/// a particular element in a collection, you can use it to access the
|
||||
/// element by subscripting. This example shows how you can modify one of
|
||||
/// the names in an array of students.
|
||||
///
|
||||
/// var students = ["Ben", "Ivy", "Jordell", "Ben", "Maxime"]
|
||||
/// if let i = students.lastIndex(of: "Ben") {
|
||||
/// students[i] = "Benjamin"
|
||||
/// }
|
||||
/// print(students)
|
||||
/// // Prints "["Ben", "Ivy", "Jordell", "Benjamin", "Max"]"
|
||||
///
|
||||
/// - Parameter element: An element to search for in the collection.
|
||||
/// - Returns: The last index where `element` is found. If `element` is not
|
||||
/// found in the collection, returns `nil`.
|
||||
@inlinable
|
||||
public func lastIndex(of element: Element) -> Index? {
|
||||
if let result = _customLastIndexOfEquatableElement(element) {
|
||||
return result
|
||||
}
|
||||
return lastIndex(where: { $0 == element })
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// partition(by:)
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Reference in New Issue
Block a user