Indexed.swift 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // This source file is part of the Swift Algorithms open source project
  4. //
  5. // Copyright (c) 2020 Apple Inc. and the Swift project authors
  6. // Licensed under Apache License v2.0 with Runtime Library Exception
  7. //
  8. // See https://swift.org/LICENSE.txt for license information
  9. //
  10. //===----------------------------------------------------------------------===//
  11. /// A collection wrapper that iterates over the indices and elements of a
  12. /// collection together.
  13. public struct IndexedCollection<Base: Collection> {
  14. /// The base collection.
  15. @usableFromInline
  16. internal let base: Base
  17. @inlinable
  18. internal init(base: Base) {
  19. self.base = base
  20. }
  21. }
  22. extension IndexedCollection: Collection {
  23. /// The element type for an `IndexedCollection` collection.
  24. public typealias Element = (index: Base.Index, element: Base.Element)
  25. @inlinable
  26. public var startIndex: Base.Index {
  27. base.startIndex
  28. }
  29. @inlinable
  30. public var endIndex: Base.Index {
  31. base.endIndex
  32. }
  33. @inlinable
  34. public subscript(position: Base.Index) -> Element {
  35. (index: position, element: base[position])
  36. }
  37. @inlinable
  38. public func index(after i: Base.Index) -> Base.Index {
  39. base.index(after: i)
  40. }
  41. @inlinable
  42. public func index(_ i: Base.Index, offsetBy distance: Int) -> Base.Index {
  43. base.index(i, offsetBy: distance)
  44. }
  45. @inlinable
  46. public func index(
  47. _ i: Base.Index,
  48. offsetBy distance: Int,
  49. limitedBy limit: Base.Index
  50. ) -> Base.Index? {
  51. base.index(i, offsetBy: distance, limitedBy: limit)
  52. }
  53. @inlinable
  54. public func distance(from start: Base.Index, to end: Base.Index) -> Int {
  55. base.distance(from: start, to: end)
  56. }
  57. @inlinable
  58. public var indices: Base.Indices {
  59. base.indices
  60. }
  61. }
  62. extension IndexedCollection: BidirectionalCollection
  63. where Base: BidirectionalCollection
  64. {
  65. @inlinable
  66. public func index(before i: Base.Index) -> Base.Index {
  67. base.index(before: i)
  68. }
  69. }
  70. extension IndexedCollection: RandomAccessCollection
  71. where Base: RandomAccessCollection {}
  72. extension IndexedCollection: LazySequenceProtocol, LazyCollectionProtocol
  73. where Base: LazySequenceProtocol {}
  74. //===----------------------------------------------------------------------===//
  75. // indexed()
  76. //===----------------------------------------------------------------------===//
  77. extension Collection {
  78. /// Returns a collection of pairs *(i, x)*, where *i* represents an index of
  79. /// the collection, and *x* represents an element.
  80. ///
  81. /// This example iterates over the indices and elements of a set, building an
  82. /// array consisting of indices of names with five or fewer letters.
  83. ///
  84. /// let names: Set = ["Sofia", "Camilla", "Martina", "Mateo", "Nicolás"]
  85. /// var shorterIndices: [Set<String>.Index] = []
  86. /// for (i, name) in names.indexed() {
  87. /// if name.count <= 5 {
  88. /// shorterIndices.append(i)
  89. /// }
  90. /// }
  91. ///
  92. /// Returns: A collection of paired indices and elements of this collection.
  93. @inlinable
  94. public func indexed() -> IndexedCollection<Self> {
  95. IndexedCollection(base: self)
  96. }
  97. }