Trim.swift 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. // trimmingPrefix(while:)
  12. //===----------------------------------------------------------------------===//
  13. extension Collection {
  14. /// Returns a `SubSequence` formed by discarding all elements at the start of
  15. /// the collection which satisfy the given predicate.
  16. ///
  17. /// This example uses `trimmingPrefix(while:)` to get a substring without the
  18. /// white space at the beginning of the string:
  19. ///
  20. /// let myString = " hello, world "
  21. /// print(myString.trimmingPrefix(while: \.isWhitespace)) // "hello, world "
  22. ///
  23. /// - Parameter predicate: A closure which determines if the element should be
  24. /// omitted from the resulting slice.
  25. ///
  26. /// - Complexity: O(*n*), where *n* is the length of this collection.
  27. ///
  28. @inlinable
  29. public func trimmingPrefix(
  30. while predicate: (Element) throws -> Bool
  31. ) rethrows -> SubSequence {
  32. let start = try endOfPrefix(while: predicate)
  33. return self[start...]
  34. }
  35. }
  36. //===----------------------------------------------------------------------===//
  37. // trimPrefix(while:)
  38. //===----------------------------------------------------------------------===//
  39. extension Collection where Self: RangeReplaceableCollection {
  40. /// Mutates a `Collection` by discarding all elements at the start of it which
  41. /// satisfy the given predicate.
  42. ///
  43. /// This example uses `trimPrefix(while:)` to remove the white space at the
  44. /// beginning of the string:
  45. ///
  46. /// let myString = " hello, world "
  47. /// myString.trimPrefix(while: \.isWhitespace)
  48. /// print(myString) // "hello, world "
  49. ///
  50. /// - Parameter predicate: A closure which determines if the element should be
  51. /// removed from the string.
  52. ///
  53. /// - Complexity: O(*n*), where *n* is the length of this collection.
  54. ///
  55. @inlinable
  56. @_disfavoredOverload
  57. public mutating func trimPrefix(
  58. while predicate: (Element) throws -> Bool
  59. ) rethrows {
  60. let end = try endOfPrefix(while: predicate)
  61. removeSubrange(startIndex..<end)
  62. }
  63. }
  64. extension Collection where Self == Self.SubSequence {
  65. /// Mutates a `Collection` by discarding all elements at the start of it which
  66. /// satisfy the given predicate.
  67. ///
  68. /// This example uses `trimPrefix(while:)` to remove the white space at the
  69. /// beginning of the string:
  70. ///
  71. /// let myString = " hello, world "
  72. /// myString.trimPrefix(while: \.isWhitespace)
  73. /// print(myString) // "hello, world "
  74. ///
  75. /// - Parameters predicate: A closure which determines if the element should
  76. /// be removed from the string.
  77. ///
  78. /// - Complexity: O(*n*), where *n* is the length of this collection.
  79. ///
  80. @inlinable
  81. public mutating func trimPrefix(
  82. while predicate: (Element) throws -> Bool
  83. ) rethrows {
  84. self = try trimmingPrefix(while: predicate)
  85. }
  86. }
  87. //===----------------------------------------------------------------------===//
  88. // trimming(while:) / trimmingSuffix(while:)
  89. //===----------------------------------------------------------------------===//
  90. extension BidirectionalCollection {
  91. /// Returns a `SubSequence` formed by discarding all elements at the start and
  92. /// end of the collection which satisfy the given predicate.
  93. ///
  94. /// This example uses `trimming(while:)` to get a substring without the white
  95. /// space at the beginning and end of the string:
  96. ///
  97. /// let myString = " hello, world "
  98. /// print(myString.trimming(while: \.isWhitespace)) // "hello, world"
  99. ///
  100. /// - Parameter predicate: A closure which determines if the element should be
  101. /// omitted from the resulting slice.
  102. ///
  103. /// - Complexity: O(*n*), where *n* is the length of this collection.
  104. ///
  105. @inlinable
  106. public func trimming(
  107. while predicate: (Element) throws -> Bool
  108. ) rethrows -> SubSequence {
  109. try trimmingPrefix(while: predicate).trimmingSuffix(while: predicate)
  110. }
  111. /// Returns a `SubSequence` formed by discarding all elements at the end of
  112. /// the collection which satisfy the given predicate.
  113. ///
  114. /// This example uses `trimmingSuffix(while:)` to get a substring without the
  115. /// white space at the end of the string:
  116. ///
  117. /// let myString = " hello, world "
  118. /// print(myString.trimmingSuffix(while: \.isWhitespace)) // " hello, world"
  119. ///
  120. /// - Parameter predicate: A closure which determines if the element should be
  121. /// omitted from the resulting slice.
  122. ///
  123. /// - Complexity: O(*n*), where *n* is the length of this collection.
  124. ///
  125. @inlinable
  126. public func trimmingSuffix(
  127. while predicate: (Element) throws -> Bool
  128. ) rethrows -> SubSequence {
  129. let end = try startOfSuffix(while: predicate)
  130. return self[..<end]
  131. }
  132. }
  133. //===----------------------------------------------------------------------===//
  134. // trim(while:) / trimSuffix(while:)
  135. //===----------------------------------------------------------------------===//
  136. extension BidirectionalCollection where Self: RangeReplaceableCollection {
  137. /// Mutates a `BidirectionalCollection` by discarding all elements at the
  138. /// start and at the end of it which satisfy the given predicate.
  139. ///
  140. /// This example uses `trim(while:)` to remove the white space at the
  141. /// beginning of the string:
  142. ///
  143. /// let myString = " hello, world "
  144. /// myString.trim(while: \.isWhitespace)
  145. /// print(myString) // "hello, world"
  146. ///
  147. /// - Parameter predicate: A closure which determines if the element should be
  148. /// removed from the string.
  149. ///
  150. /// - Complexity: O(*n*), where *n* is the length of this collection.
  151. ///
  152. @inlinable
  153. @_disfavoredOverload
  154. public mutating func trim(
  155. while predicate: (Element) throws -> Bool
  156. ) rethrows {
  157. try trimSuffix(while: predicate)
  158. try trimPrefix(while: predicate)
  159. }
  160. /// Mutates a `BidirectionalCollection` by discarding all elements at the end
  161. /// of it which satisfy the given predicate.
  162. ///
  163. /// This example uses `trimSuffix(while:)` to remove the white space at the
  164. /// beginning of the string:
  165. ///
  166. /// let myString = " hello, world "
  167. /// myString.trimSuffix(while: \.isWhitespace)
  168. /// print(myString) // " hello, world"
  169. ///
  170. /// - Parameter predicate: A closure which determines if the element should be
  171. /// removed from the string.
  172. ///
  173. /// - Complexity: O(*n*), where *n* is the length of this collection.
  174. ///
  175. @inlinable
  176. @_disfavoredOverload
  177. public mutating func trimSuffix(
  178. while predicate: (Element) throws -> Bool
  179. ) rethrows {
  180. let start = try startOfSuffix(while: predicate)
  181. removeSubrange(start..<endIndex)
  182. }
  183. }
  184. extension BidirectionalCollection where Self == Self.SubSequence {
  185. /// Mutates a `BidirectionalCollection` by discarding all elements at the
  186. /// start and at the end of it which satisfy the given predicate.
  187. ///
  188. /// This example uses `trim(while:)` to remove the white space at the
  189. /// beginning of the string:
  190. ///
  191. /// let myString = " hello, world "
  192. /// myString.trim(while: \.isWhitespace)
  193. /// print(myString) // "hello, world"
  194. ///
  195. /// - Parameter predicate: A closure which determines if the element should be
  196. /// removed from the string.
  197. ///
  198. /// - Complexity: O(*n*), where *n* is the length of this collection.
  199. ///
  200. @inlinable
  201. public mutating func trim(
  202. while predicate: (Element) throws -> Bool
  203. ) rethrows {
  204. self = try trimming(while: predicate)
  205. }
  206. /// Mutates a `BidirectionalCollection` by discarding all elements at the end
  207. /// of it which satisfy the given predicate.
  208. ///
  209. /// This example uses `trimSuffix(while:)` to remove the white space at the
  210. /// beginning of the string:
  211. ///
  212. /// let myString = " hello, world "
  213. /// myString.trimSuffix(while: \.isWhitespace)
  214. /// print(myString) // " hello, world"
  215. ///
  216. /// - Parameter predicate: A closure which determines if the element should be
  217. /// removed from the string.
  218. ///
  219. /// - Complexity: O(*n*), where *n* is the length of this collection.
  220. ///
  221. @inlinable
  222. public mutating func trimSuffix(
  223. while predicate: (Element) throws -> Bool
  224. ) rethrows {
  225. self = try trimmingSuffix(while: predicate)
  226. }
  227. }