Last active
February 12, 2018 20:53
-
-
Save surakamy/5e84d96e2fe7d21cb31e1438538dee02 to your computer and use it in GitHub Desktop.
Extension to Array - split at indices
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension Array { | |
/// Returns the longest possible subsequences of the collection, in order, | |
/// that don't contain elements at indices provided. | |
/// | |
/// The resulting array consists of at most `maxSplits + 1` subsequences. | |
/// Elements that are used to split the sequence are not returned as part of | |
/// any subsequence. | |
/// | |
/// - Parameters: | |
/// - maxSplits: The maximum number of times to split the collection, or | |
/// one less than the number of subsequences to return. If | |
/// `maxSplits + 1` subsequences are returned, the last one is a suffix | |
/// of the original collection containing the remaining elements. | |
/// `maxSplits` must be greater than or equal to zero. The default value | |
/// is `Int.max`. | |
/// - omittingEmptySubsequences: If `false`, an empty subsequence is | |
/// returned in the result for each pair of consecutive elements | |
/// satisfying the `isSeparator` predicate and for each element at the | |
/// start or end of the collection satisfying the `isSeparator` | |
/// predicate. The default value is `true`. | |
/// - indices: variadic parameter containing indices at which collection should be splitted. Elements at these indices are removed from resulting collections. Indices out of bounds are ignored. | |
/// - Returns: An array of subsequences, split from this collection's | |
/// elements. | |
func split(maxSplits: Int = Int.max, | |
omittingEmptySubsequences: Bool = true, | |
at indices: Int...) -> [ArraySlice<Element>] | |
{ | |
// Prepare safe indices | |
var safeIndices = indices | |
safeIndices = indices.filter{ startIndex...endIndex ~= $0 } | |
let skip = safeIndices.count - maxSplits | |
if skip > 0 { safeIndices.removeLast(skip) } | |
safeIndices.append(endIndex) | |
//Slide though array by indices forming slices | |
var slices: [ArraySlice<Array.Element>] = [] | |
var lo = startIndex | |
for idx in safeIndices { | |
slices.append(self[lo..<idx]) | |
lo = index(after: idx) | |
} | |
if omittingEmptySubsequences { | |
return slices.flatMap{ $0.isEmpty ? nil : $0 } | |
} | |
return slices | |
} | |
} | |
let numbers = Array(1...10) | |
numbers.split(at: 5) | |
//[[1, 2, 3, 4, 5], [7, 8, 9, 10]] | |
numbers.split(at: 5, 6, 8) | |
//[[1, 2, 3, 4, 5], [8], [10]] | |
numbers.split(omittingEmptySubsequences: false, at: 1, 2) | |
//[[1], ArraySlice([]), [4, 5, 6, 7, 8, 9, 10]] | |
numbers.split(maxSplits: 1, at: 5, 6, 8) | |
//[[1, 2, 3, 4, 5], [7, 8, 9, 10]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment