apple / swift-algorithms

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

Add `replaceOccurrences(of:with:)` #156

Closed timvermeulen closed 1 year ago

timvermeulen commented 3 years ago

Depends on #155.

Replace occurrences of a given subsequence with a given replacement.

The lazy overloads are available on all lazy collections while the eager ones are only available on range-replaceable collections, which is a little odd.

extension RangeReplaceableCollection {
  public func replacingOccurrences<Target: Collection, Replacement: Collection>(
    of target: Target,
    with replacement: Replacement,
    subrange: Range<Index>,
    maxReplacements: Int = .max,
    by areEquivalent: (Element, Target.Element) throws -> Bool
  ) rethrows -> Self where Replacement.Element == Element

  public func replacingOccurrences<Target: Collection, Replacement: Collection>(
    of target: Target,
    with replacement: Replacement,
    maxReplacements: Int = .max,
    by areEquivalent: (Element, Target.Element) throws -> Bool
  ) rethrows -> Self where Replacement.Element == Element
}

extension RangeReplaceableCollection where Element: Equatable {
  public func replacingOccurrences<Target: Collection, Replacement: Collection>(
    of target: Target,
    with replacement: Replacement,
    subrange: Range<Index>,
    maxReplacements: Int = .max
  ) -> Self where Target.Element == Element, Replacement.Element == Element

  public func replacingOccurrences<Target: Collection, Replacement: Collection>(
    of target: Target,
    with replacement: Replacement,
    maxReplacements: Int = .max
  ) -> Self where Target.Element == Element, Replacement.Element == Element
}

extension LazyCollectionProtocol {
  public func replacingOccurrences<Target: Collection, Replacement: Collection>(
    of target: Target,
    with replacement: Replacement,
    subrange: Range<Elements.Index>,
    maxReplacements: Int = .max,
    by areEquivalent: @escaping (Element, Target.Element) -> Bool
  ) -> LazyCollection<
    Chain2<
      Elements.SubSequence,
      Chain2<
        JoinedByCollection<
          SplitCollection<Elements.SubSequence, Target>,
          Replacement
        >,
        Elements.SubSequence
      >
    >
  > where Replacement.Element == Element

  public func replacingOccurrences<Target: Collection, Replacement: Collection>(
    of target: Target,
    with replacement: Replacement,
    maxReplacements: Int = .max,
    by areEquivalent: @escaping (Element, Target.Element) -> Bool
  ) -> JoinedByCollection<
         LazyCollection<SplitCollection<Elements, Target>>, Replacement>
    where Replacement.Element == Element
}

extension LazyCollectionProtocol where Element: Equatable {
  public func replacingOccurrences<Target: Collection, Replacement: Collection>(
    of target: Target,
    with replacement: Replacement,
    subrange: Range<Elements.Index>,
    maxReplacements: Int = .max
  ) -> LazyCollection<
    Chain2<
      Elements.SubSequence,
      Chain2<
        JoinedByCollection<
          SplitCollection<Elements.SubSequence, Target>,
          Replacement
        >,
        Elements.SubSequence
      >
    >
  > where Target.Element == Element, Replacement.Element == Element

  public func replacingOccurrences<Target: Collection, Replacement: Collection>(
    of target: Target,
    with replacement: Replacement,
    maxReplacements: Int = .max
  ) -> JoinedByCollection<
         LazyCollection<SplitCollection<Elements, Target>>, Replacement>
    where Target.Element == Element, Replacement.Element == Element
}

extension RangeReplaceableCollection {
  public mutating func replaceOccurrences<
    Target: Collection,
    Replacement: Collection
  >(
    of target: Target,
    with replacement: Replacement,
    maxReplacements: Int = .max,
    by areEquivalent: (Element, Target.Element) throws -> Bool
  ) rethrows where Replacement.Element == Element
}

extension RangeReplaceableCollection where Element: Equatable {
  public mutating func replaceOccurrences<
    Target: Collection,
    Replacement: Collection
  >(
    of target: Target,
    with replacement: Replacement,
    maxReplacements: Int = .max
  ) where Target.Element == Element, Replacement.Element == Element
}

Checklist

natecook1000 commented 1 year ago

This functionality is handled by the string-processing package.