apple / swift-algorithms

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

`AdjacentPairs`: Ability to also include the (last, first) pair #140

Open mdznr opened 3 years ago

mdznr commented 3 years ago

Summary: Add ability to optionally also include the pair of the last element and the first element at the end of AdjacentPairs.

Use Case: For use with circular linked links. Today, I was working with the key view loop on macOS and needed to be able to tie the last element in the loop back to the first. AdjacentPairs almost made this really easy, but was missing the pair of (last, first) so I couldn’t connect them together to be a loop.

for (previousView, nextView) in keyViewLoop.adjacentPairs(wrapping: true) {
  previousView.nextKeyView = nextView
}

Possible API:

I’m not sure if this should be a separate API, or if this extends AdjacentPairs

extension Sequence {
  /// …
  /// The following example uses `adjacentPairs(wrapping: true)` to iterate over
  /// adjacent pairs of integers:
  ///
  ///     for pair in (1...).prefix(5).adjacentPairs(wrapping: true) {
  ///         print(pair)
  ///     }
  ///     // Prints "(1, 2)"
  ///     // Prints "(2, 3)"
  ///     // Prints "(3, 4)"
  ///     // Prints "(4, 5)"
  ///     // Prints "(5, 1)"
  @inlinable
  public func adjacentPairs(wrapping: Bool = false) -> AdjacentPairsSequence<Self> {
    AdjacentPairsSequence(base: self, wrapping: wrapping)
  }
}

extension Collection {
  /// …
  ///     for pair in (1...5).adjacentPairs(wrapping: true) {
  ///         print(pair)
  ///     }
  ///     // Prints "(1, 2)"
  ///     // Prints "(2, 3)"
  ///     // Prints "(3, 4)"
  ///     // Prints "(4, 5)"
  ///     // Prints "(5, 1)"
  @inlinable
  public func adjacentPairs(wrapping: Bool = false) -> AdjacentPairsCollection<Self> {
    AdjacentPairsCollection(base: self, wrapping: wrapping)
  }
}