Skip to content

Add indexBeforeFirst(where:) and indexAfterLast(where:) #23

Closed
@kylemacomber

Description

@kylemacomber

In #4 the implementation of trimmed(where:) requires a raw loop because using lastIndex(where:) would require making an extra call to index(after:) to advanced the returned index.

The embracing algorithms talk exhibits the need for the dual—the index before firstIndex(where:)—to avoid a raw loop or an extra call to index(before:):

extension MutableCollection {
    mutating func bringForward(elementsSatisfying predicate: (Element) -> Bool) {
        if let predecessor = indexBeforeFirst(where: predicate) {
            self[predecessor...].stablePartition(isSuffixElement: { !predicate($0) })
        }
    }
}

extension Collection {
    func indexBeforeFirst(where predicate: (Element) -> Bool) -> Index? {
        return indices.first {
            let successor = index(after: $0)
            return successor != endIndex && predicate(self[successor])
        }
    } 
}

These use cases seem like sufficient justification to add these algorithms.

Though I wonder if indexBeforeFirst(where:)/indexAfterLast(where:) or firstIndex(before:)/lastIndex(after:) or some other naming scheme is best?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions