[swift-evolution] Proposal: Filter split extension on Sequence to return tuple of sequences that meet criteria and that do not
plx
plxswift at icloud.com
Thu Jun 9 11:22:50 CDT 2016
This reminds me of something: I *very* often wish the standard library had an analog to `NSIndexSet`.
I bring it up b/c it would allow, here, for IMHO a rather nice way to write the *eager* variant of this `filterSplit` (or preferably imho, `partition`, if not for the *other* `partition` out there) function:
extension Collection {
/// Returns the index-sets upon which `predicate(self[$index])` evaluates to `true` and `false`, respectively,
func partitionedIndices(predicate: (Element) -> Bool) -> (IndexSet<Self.Index>, IndexSet<Self.Index>)
}
…from which—with a suitable IndexSet implementation!—it would then be easy to construct filtered views into the original collections (and even filtered collections, at least for e.g. range-replaceable collections).
It’d be nice to see such a type make it in at some point!
In the interim, a reasonable “primitive” it’d be nice to have in the standard library would be some methods like this:
extension Collection {
func classified<T:Equatable>(classifier: (Element) -> T) -> [(T,Range<Self.Index>)]
func lazilyClassified<T:Equatable>(classifier: (Element) -> T) -> LazyClassificationSequence<Self,T>
}
…for which the semantics should be s.t. the below is a correct implementation of `filterSplit` (spelling them out more-precisely is doable but tedious):
extension RangeReplaceableCollection {
func filterSplit(predicate: (Element) -> Bool) -> (Self,Self) {
guard !self.isEmpty else { return (Self(), Self() }
var trues: Self = Self()
var falses: Self = Self()
for (classification,range) in self.lazilyClassified(predicate) {
switch classification {
case true: trues.appendContents(of: self[range])
case false: falses.appendContents(of: self[range])
}
}
return (trues,falses)
}
}
…which could also be generalized further (e.g. for T:Hashable, to then return `[T:Self]`, etc.).
Such “classification” methods would have broader-uses than implementing `filterSplit`; is there a specific reason something analogous isn’t already in the standard library (or shouldn’t be)?
Likewise, would an `IndexSet` type be something that could make it into the standard library at some point? (It'd have some API-design issues to sort out under collections-move-indices, but nothing that seems truly insurmountable.)
> On Jun 8, 2016, at 10:10 AM, gadiraju praneeth via swift-evolution <swift-evolution at swift.org> wrote:
>
> 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
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
More information about the swift-evolution
mailing list