apple / swift-algorithms

Commonly used sequence and collection algorithms for Swift
Apache License 2.0
5.92k stars 440 forks source link

Add `firstRange(of:)`, `lastRange(of:)`, `contains(_:)` #154

Closed timvermeulen closed 1 year ago

timvermeulen commented 3 years ago

Find the location of a subsequence in a collection.

extension Collection {
  public func firstRange<Other: Collection>(
    of other: Other,
    by areEquivalent: (Element, Other.Element) throws -> Bool
  ) rethrows -> Range<Index>?
}

extension Collection where Element: Equatable {
  public func firstRange<Other: Collection>(of other: Other) -> Range<Index>?
}

extension BidirectionalCollection {
  public func lastRange<Other: BidirectionalCollection>(
    of other: Other,
    by areEquivalent: (Element, Other.Element) throws -> Bool
  ) rethrows -> Range<Index>?
}

extension BidirectionalCollection where Element: Equatable {
  public func lastRange<Other: BidirectionalCollection>(
    of other: Other
  ) -> Range<Index>? where Other.Element == Element
}

extension Collection {
  public func contains<Other: Collection>(
    _ other: Other,
    by areEquivalent: (Element, Other.Element) throws -> Bool
  ) rethrows -> Bool
}

extension Collection where Element: Equatable {
  public func contains<Other: Collection>(
    _ other: Other
  ) -> Bool where Other.Element == Element
}

Checklist

mdznr commented 3 years ago

There could probably be optimizations based on count.

For example, if other’s count is larger than self, then there’s no point in iterating through self since it could never contain a larger collection as a subsequence. That’s just a base case that could be checked up front. However, this can also happen in the middle of the algorithm. For example, if we had a self.count of 20, and an other.count of 5, if we ever get a starting index (matchStart) past the 15th element, we can then just return nil since we can’t fit a subsequence of 5 with only 4 elements remaining.

glessard commented 3 years ago

@mdznr Such an optimization would only work for a RandomAccessCollection, and these are not specialized for those indexing semantics (yet.)

natecook1000 commented 1 year ago

This functionality is handled by the string-processing package.