Skip to content

Commit 2404013

Browse files
authored
[SE-0270] Add Collection Operations on Noncontiguous Elements (#69766)
* Adds RangeSet/DiscontiguousSlice to the stdlib * Remove redundant DiscontiguousSlice.Index: Comparable conformance * Attempt to fix embedded build * Attempt to fix macOS test failures * Fix Constaints/members.swift failure on linux * Add exceptions to ABI/source checker to fix macOS tests * Fix incremental dependency test failure * Remove inlining/unfreeze implementation for future improvements * Simplify indices(where:) implementation * Address review feedback * Add test for underscored, public slice members * Address feedback on inlining, hashing, and initializing with unordered arrays * Fix ABI checker issues * Remove MutableCollection extension for DiscontiguousSlice * Make insertion return a discardable Bool * Fix ABI checker tests * Fix other ABI checker tests due to dropping MutableCollection subscript
1 parent 4b8e41b commit 2404013

File tree

15 files changed

+3500
-4796
lines changed

15 files changed

+3500
-4796
lines changed

stdlib/public/core/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ split_embedded_sources(
7171
NORMAL DictionaryCasting.swift
7272
NORMAL DictionaryStorage.swift
7373
NORMAL DictionaryVariant.swift
74+
NORMAL DiscontiguousSlice.swift
7475
NORMAL DropWhile.swift
7576
NORMAL Dump.swift
7677
EMBEDDED EmptyCollection.swift
@@ -129,6 +130,8 @@ split_embedded_sources(
129130
EMBEDDED RandomAccessCollection.swift
130131
EMBEDDED Range.swift
131132
EMBEDDED RangeReplaceableCollection.swift
133+
NORMAL RangeSet.swift
134+
NORMAL RangeSetRanges.swift
132135
NORMAL ReflectionMirror.swift
133136
EMBEDDED Repeat.swift
134137
NORMAL REPL.swift

stdlib/public/core/CollectionAlgorithms.swift

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -209,6 +209,74 @@ extension BidirectionalCollection where Element: Equatable {
209209
}
210210
}
211211

212+
//===----------------------------------------------------------------------===//
213+
// indices(where:) / indices(of:)
214+
//===----------------------------------------------------------------------===//
215+
216+
#if !$Embedded
217+
extension Collection {
218+
/// Returns the indices of all the elements that match the given predicate.
219+
///
220+
/// For example, you can use this method to find all the places that a
221+
/// vowel occurs in a string.
222+
///
223+
/// let str = "Fresh cheese in a breeze"
224+
/// let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
225+
/// let allTheVowels = str.indices(where: { vowels.contains($0) })
226+
/// // str[allTheVowels].count == 9
227+
///
228+
/// - Parameter predicate: A closure that takes an element as its argument
229+
/// and returns a Boolean value that indicates whether the passed element
230+
/// represents a match.
231+
/// - Returns: A set of the indices of the elements for which `predicate`
232+
/// returns `true`.
233+
///
234+
/// - Complexity: O(*n*), where *n* is the length of the collection.
235+
@available(SwiftStdlib 5.11, *)
236+
@inlinable
237+
public func indices(
238+
where predicate: (Element) throws -> Bool
239+
) rethrows -> RangeSet<Index> {
240+
var result: [Range<Index>] = []
241+
var end = startIndex
242+
while let begin = try self[end...].firstIndex(where: predicate) {
243+
end = try self[begin...].prefix(while: predicate).endIndex
244+
result.append(begin ..< end)
245+
246+
guard end < self.endIndex else {
247+
break
248+
}
249+
self.formIndex(after: &end)
250+
}
251+
252+
return RangeSet(_orderedRanges: result)
253+
}
254+
}
255+
256+
extension Collection where Element: Equatable {
257+
/// Returns the indices of all the elements that are equal to the given
258+
/// element.
259+
///
260+
/// For example, you can use this method to find all the places that a
261+
/// particular letter occurs in a string.
262+
///
263+
/// let str = "Fresh cheese in a breeze"
264+
/// let allTheEs = str.indices(of: "e")
265+
/// // str[allTheEs].count == 7
266+
///
267+
/// - Parameter element: An element to look for in the collection.
268+
/// - Returns: A set of the indices of the elements that are equal to
269+
/// `element`.
270+
///
271+
/// - Complexity: O(*n*), where *n* is the length of the collection.
272+
@available(SwiftStdlib 5.11, *)
273+
@inlinable
274+
public func indices(of element: Element) -> RangeSet<Index> {
275+
indices(where: { $0 == element })
276+
}
277+
}
278+
#endif
279+
212280
//===----------------------------------------------------------------------===//
213281
// partition(by:)
214282
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)