[swift-evolution] Proposal: Filter split extension on Sequence to return tuple of sequences that meet criteria and that do not
Brent Royal-Gordon
brent at architechies.com
Thu Jun 9 02:54:24 CDT 2016
> Many times, I came across a scenario where I had to filter an array with a condition and filter the same array with opposite of that condition. For example:
>
> let values = [2, 4, 3, 5, 6, 9]
>
> let divisibleByTwo = values.filter { $0 % 2 == 0 }
> let notDivisibleByTwo = values.filter { $0 % 2 != 0 }
>
> Is there a way currently where we can filter the array into two arrays based on a condition?
>
> If not how about something like a filterSplit function where we get a tuple of values:
>
> values.filterSplit { $0 % 2 == 0 } = ([2,4,6], [3,5,9])
>
> I have implemented this in our project and wanted to get your thoughts on it
Dave's got a pretty nice solution for the true-or-false case. If SE-0100 ("Add sequence-based initializers and merge methods to Dictionary", https://github.com/apple/swift-evolution/blob/master/proposals/0100-add-sequence-based-init-and-merge-to-dictionary.md) is accepted, you could also write an N-way, key-based version that works with any type:
let pairs = values.map { ($0 % 3, [$0]) }
let byThrees: [Int: Int] = Dictionary(merging: pairs, combine: +)
One could also imagine an array-based N-way version, though I'm not aware of a particularly easy-to-write implementation for it.
extension Collection {
func partition(by indexer: @noescape (Element) throws -> Int) rethrows -> [[Iterator.Element]] {
var output = [] as [[Iterator.Element]]
for elem in self {
let index = try indexer(elem)
while index >= output.endIndex {
output.append([])
}
output[index].append(elem)
}
return output
}
}
let byThrees: [Int] = values.partition { $0 % 3 }
--
Brent Royal-Gordon
Architechies
More information about the swift-evolution
mailing list