Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
extension Collection where Iterator.Element: Comparable {
/// Returns an eagerly composed array of ordered elements
/// split at each point where a user-supplied predicate
/// evaluates to true.
///
/// ```
/// [1, 2, 2, 3, 3, 3, 1]
/// .partitioned(at: { $0 != $1.last! })
/// // [[1], [2, 2], [3, 3, 3], [1]]
///
/// [1, 2, 2, 3, 3, 3, 1]
/// .partitioned(at: { $0.count == 2 })
/// // [[1 2], [2, 3], [3, 3], [1]]
/// ```
///
/// - Parameter predicate: a closure that tests whether a new element
/// should be added to the current partion
/// - Parameter element: the element to be tested
/// - Parameter currentPartition: a non-empty array, containing a
/// an ordered contiguous group of collection members
///
/// - Returns: An array of partitioned collection elements
public func partitioned(at predicate: (_ element: Iterator.Element, _ currentPartition: [Iterator.Element]) -> Bool ) -> [[Iterator.Element]] {
var current: [Iterator.Element] = []
var results: [[Iterator.Element]] = []
for element in self {
guard !current.isEmpty else { current = [element]; continue }
switch predicate(element, current) {
case true: results.append(current); current = [element]
case false: current.append(element)
}
}
guard !current.isEmpty else { return results }
results.append(current)
return results
}
/// Returns an eagerly composed array of ordered elements
/// split at each point where a user-supplied predicate
/// evaluates to true.
///
/// ```
/// [1, 2, 2, 3, 3, 3, 1]
/// .partitioned(where: !=)
/// // [[1], [2, 2], [3, 3, 3], [1]]
/// ```
///
/// - Parameter predicate: a closure that tests whether a new element
/// should be added to the current partion
/// - Parameter element: the element to be tested
/// - Parameter mostRecent: the most recently included element
///
/// - Returns: An array of partitioned collection elements
public func partitioned(where predicate: @escaping (_ element: Iterator.Element, _ mostRecent: Iterator.Element) -> Bool ) -> [[Iterator.Element]] {
// `partitioned(at:)` guarantees a non-empty array
// as its second closure argument
return self.partitioned(at: {
return predicate($0, $1.last!)
})
}
}
let testArray = [1, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 3]
print(testArray.partitioned(at: { $0 != $1.last! }))
// [[1], [2, 2], [3, 3, 3], [1, 1, 1], [2, 2], [3]]
print(testArray.partitioned(where: !=))
// [[1], [2, 2], [3, 3, 3], [1, 1, 1], [2, 2], [3]]
print(testArray.partitioned(at: { $0 == $1.last! }))
// [[1, 2], [2, 3], [3], [3, 1], [1], [1, 2], [2, 3]]
print(testArray.partitioned(at: { $1.count == 5 }))
// [[1, 2, 2, 3, 3], [3, 1, 1, 1, 2], [2, 3]]
print([1, 2, 2, 3, 3, 3, 1].partitioned(at: { $1.count == 2 }))
// [[1, 2], [2, 3], [3, 3], [1]]
print("1223333111223"
.characters
.partitioned(at: { $0 != $1.last! })
.map({ String($0) }))
// ["1", "22", "3333", "111", "22", "3"]
print("1223333111223"
.characters
.partitioned(where: !=)
.map({ String($0) }))
// ["1", "22", "3333", "111", "22", "3"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment