Skip to content

Instantly share code, notes, and snippets.

@CTMacUser
Last active May 14, 2020 15:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CTMacUser/96b3d851ea08536a69e753c89a70b035 to your computer and use it in GitHub Desktop.
Save CTMacUser/96b3d851ea08536a69e753c89a70b035 to your computer and use it in GitHub Desktop.
extension Collection {
/// If the collection does not have the given sequence as a prefix when
/// using the given predicate to compare elements, returns the collection
/// as-is; otherwise, returns the part of the collection after that prefix.
///
/// The predicate must be an equivalence relation over the elements.
///
/// Whether a prefix was actually dropped can be tested by checking if the
/// returned sub-sequence's `startIndex` is greater than the collection's
/// starting index.
///
/// - Parameters:
/// - possiblePrefix: A sequence to compare to this collection.
/// - areEquivalent: A predicate that returns `true` if its two
/// arguments are equivalent; otherwise, `false`.
/// - Returns: Either `dropFirst(Array(possiblePrefix).count)` or `self`,
/// depending on `starts(with: possiblePrefix, by: areEquivalent)`.
///
/// - Complexity: O(*n*), where *n* is the shorter of this collection and
/// `possiblePrefix`.
public func dropPrefix<S: Sequence>(
of possiblePrefix: S,
by areEquivalent: (Element, S.Element) throws -> Bool
) rethrows -> SubSequence {
let delta = try possiblePrefix.firstDelta(against: indices) {
try areEquivalent(self[$1], $0)
}
if delta.0 == nil {
return self[(delta.1 ?? endIndex)...]
} else {
return self[...]
}
}
}
extension Collection where Element: Equatable {
/// If the collection starts with the given sequence as a prefix, returns
/// the part of the collection after the prefix; otherwise, returns the
/// collection as-is.
///
/// Whether a prefix was actually dropped can be tested by checking if the
/// returned sub-sequence's `startIndex` is greater than the collection's
/// starting index.
///
/// - Parameters:
/// - possiblePrefix: A sequence to compare to this collection.
/// - Returns: Either `dropFirst(Array(possiblePrefix).count)` or `self`,
/// depending on `starts(with: possiblePrefix)`.
///
/// - Complexity: O(*n*), where *n* is the shorter of this collection and
/// `possiblePrefix`.
@inlinable
public func dropPrefix<S: Sequence>(of possiblePrefix: S) -> SubSequence
where S.Element == Element {
return dropPrefix(of: possiblePrefix, by: ==)
}
}
extension BidirectionalCollection {
/// If this collection does not have the given collection as a suffix when
/// using the given predicate to compare elements, returns this collection
/// as-is; otherwise, returns the part of this collection before that
/// suffix.
///
/// The predicate must be an equivalence relation over the elements.
///
/// Whether a suffix was actually dropped can be tested by checking if the
/// returned sub-sequence's `endIndex` is less than this collection's
/// past-the-end index.
///
/// - Parameters:
/// - possibleSuffix: A collection to compare to this collection.
/// - areEquivalent: A predicate that returns `true` if its two
/// arguments are equivalent; otherwise, `false`.
/// - Returns: Either `dropLast(Array(possibleSuffix).count)` or `self`,
/// depending on this collection's suffix.
///
/// - Complexity: O(*n*), where *n* is the shorter of this collection and
/// `possibleSuffix`.
@inlinable
public func dropSuffix<C: BidirectionalCollection>(
of possibleSuffix: C,
by areEquivalent: (Element, C.Element) throws -> Bool
) rethrows -> SubSequence {
let result = try reversed().dropPrefix(of: possibleSuffix.reversed(), by: areEquivalent)
return self[result.endIndex.base ..< result.startIndex.base]
}
}
extension BidirectionalCollection where Element: Equatable {
/// If this collection starts with the given collection as a suffix, returns
/// the part of this collection before the suffix; otherwise, returns this
/// collection as-is.
///
/// Whether a suffix was actually dropped can be tested by checking if the
/// returned sub-sequence's `endIndex` is less than this collection's
/// past-the-end index.
///
/// - Parameters:
/// - possibleSuffix: A collection to compare to this collection.
/// - Returns: Either `dropFirst(Array(possibleSuffix).count)` or `self`,
/// depending on this collection's suffix.
///
/// - Complexity: O(*n*), where *n* is the shorter of this collection and
/// `possibleSuffix`.
@inlinable
public func dropSuffix<C: BidirectionalCollection>(of possibleSuffix: C)
-> SubSequence where C.Element == Element {
return dropSuffix(of: possibleSuffix, by: ==)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment