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
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022 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
//
//===----------------------------------------------------------------------===//
extension Array {
/// Coalesce adjacent elements using a given accumulator. The accumulator is
/// transformed into elements of the array by `finish`. The `accumulate`
/// function should return `true` if the accumulator has coalesced the
/// element, `false` otherwise.
func coalescing<T>(
with initialAccumulator: T, into finish: (T) -> Self,
accumulate: (inout T, Element) -> Bool
) -> Self {
var didAccumulate = false
var accumulator = initialAccumulator
var result = Self()
for elt in self {
if accumulate(&accumulator, elt) {
// The element has been coalesced into accumulator, there is nothing
// else to do.
didAccumulate = true
continue
}
if didAccumulate {
// We have a leftover accumulator, which needs to be finished before we
// can append the next element.
result += finish(accumulator)
accumulator = initialAccumulator
didAccumulate = false
}
result.append(elt)
}
// Handle a leftover accumulation.
if didAccumulate {
result += finish(accumulator)
}
return result
}
/// Coalesce adjacent elements using a given accumulator. The accumulator is
/// transformed into an element of the array by `finish`. The `accumulate`
/// function should return `true` if the accumulator has coalesced the
/// element, `false` otherwise.
func coalescing<T>(
with initialAccumulator: T, into finish: (T) -> Element,
accumulate: (inout T, Element) -> Bool
) -> Self {
coalescing(
with: initialAccumulator, into: { [finish($0) ]}, accumulate: accumulate)
}
}
/// An enum for quick-check functions, which could return an answer or indefinite.
/// We use a separate type because often the answer itself is optional.
enum QuickResult<R> {
case definite(_ r: R)
case unknown
}
extension String {
/// Index after in either grapheme or scalar view
func index(after idx: Index, isScalarSemantics: Bool) -> Index {
if isScalarSemantics {
return unicodeScalars.index(after: idx)
} else {
return index(after: idx)
}
}
}
|