File: LazySplitSequence.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (103 lines) | stat: -rw-r--r-- 3,364 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

/// A sequence that lazily computes the longest possible subsequences of a collection, in order,
/// around elements equal to a specific element.
struct LazySplitSequence<Base: Collection>: Sequence where Base.Element: Equatable {
  /// The base collection.
  private let base: Base

  /// The element around which to split.
  private let separator: Base.Element

  /// The number of subsequences, which is precomputed when the sequence is initialized.
  let count: Int

  var underestimatedCount: Int {
    return count
  }

  /// Creates a new sequence that lazily computes the longest possible subsequences of a collection,
  /// in order, around elements equal to the given element.
  fileprivate init(base: Base, separator: Base.Element) {
    self.base = base
    self.separator = separator

    // Precompute the number of subsequences.
    var count = 1
    for element in base where element == separator {
      count += 1
    }
    self.count = count
  }

  func makeIterator() -> Iterator {
    return Iterator(base: base, separator: separator)
  }

  struct Iterator: IteratorProtocol {
    private let base: Base
    private let separator: Base.Element

    /// The start index of the current subsequence being computed.
    private var subSequenceStart: Base.Index

    /// The end index of the current subsequence being computed.
    private var subSequenceEnd: Base.Index

    /// The end index of the base collection.
    private let endIndex: Base.Index

    /// Indicates whether the last subsequence has been computed.
    private var done: Bool

    init(base: Base, separator: Base.Element) {
      self.base = base
      self.separator = separator

      self.subSequenceStart = base.startIndex
      self.subSequenceEnd = self.subSequenceStart
      self.endIndex = base.endIndex
      self.done = false
    }

    mutating func next() -> Base.SubSequence? {
      while subSequenceEnd != endIndex {
        if base[subSequenceEnd] == separator {
          let next = base[subSequenceStart..<subSequenceEnd]
          base.formIndex(after: &subSequenceEnd)
          subSequenceStart = subSequenceEnd
          return next
        }
        base.formIndex(after: &subSequenceEnd)
      }

      if !done {
        done = true
        return base[subSequenceStart..<endIndex]
      }

      return nil
    }
  }
}

extension Collection where Element: Equatable {
  /// Returns a `Sequence` that lazily computes the longest possible subsequences of the collection,
  /// in order, around elements equal to the given element.
  ///
  /// - Parameter separator: The element that should be split upon.
  /// - Returns: A sequence of subsequences, split from this collection’s elements.
  func lazilySplit(separator: Element) -> LazySplitSequence<Self> {
    return LazySplitSequence(base: self, separator: separator)
  }
}