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@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@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to