Proposal: Filter split extension on Sequence to return tuple of sequences that meet criteria and that do not


(gadiraju praneeth) #1

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 Abrahams) #2

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?

Well, you need a stable partition for this if you care about ordering
(see
https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift#L299)
but then you can do

var parts = values
let mid = values.stablePartition { $0 % 2 == 0 }
let divisibleByTwo = parts.prefix(upTo: mid)
let notDivisibleByTwo = parts.suffix(from: mid)

Nate Cook has an enhancement to the result of stablyPartitioned in that
prototype that would let you write:

  let parts = values.stablyPartitioned { $0 % 2 == 0 }
  let divisibleByTwo = parts.prefix(upTo: parts.partitionPoint)
  let notDivisibleByTwo = parts.suffix(from: parts.partitionPoint)

···

on Wed Jun 08 2016, gadiraju praneeth <swift-evolution@swift.org> wrote:

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

--
Dave


(Brent Royal-Gordon) #3

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


(plx) #4

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


(Dave Abrahams) #5

Hmm, come to think of it, Nate, maybe there should also be a more
convenient way to get the two partitions from the result.

···

on Wed Jun 08 2016, Dave Abrahams <swift-evolution@swift.org> wrote:

on Wed Jun 08 2016, gadiraju praneeth <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?

Well, you need a stable partition for this if you care about ordering
(see
https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift#L299)
but then you can do

var parts = values
let mid = values.stablePartition { $0 % 2 == 0 }
let divisibleByTwo = parts.prefix(upTo: mid)
let notDivisibleByTwo = parts.suffix(from: mid)

Nate Cook has an enhancement to the result of stablyPartitioned in that
prototype that would let you write:

  let parts = values.stablyPartitioned { $0 % 2 == 0 }
  let divisibleByTwo = parts.prefix(upTo: parts.partitionPoint)
  let notDivisibleByTwo = parts.suffix(from: parts.partitionPoint)

--
Dave


(gadiraju praneeth) #6

I added an extension to do this, something like this:

extension Array {

    func filterSplit(includeElement: (Element) -> Bool) -> ([Element],
[Element]) {

        var elementsSatisfyingCondition = [Element]()

        var elementsNotSatisfyingCondition = [Element]()

        self.forEach { element in

            if includeElement(element)
{ elementsSatisfyingCondition.append(element) }

            else { elementsNotSatisfyingCondition.append(element) }

        }

        return (elementsSatisfyingCondition, elementsNotSatisfyingCondition)

    }

}

that way you can right away do: values.filterSplit { <yourPredicateBlock> }

···

On Wed, Jun 8, 2016 at 3:40 PM, Dave Abrahams via swift-evolution < swift-evolution@swift.org> wrote:

on Wed Jun 08 2016, Dave Abrahams <swift-evolution@swift.org> wrote:

> on Wed Jun 08 2016, gadiraju praneeth <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?
>
> Well, you need a stable partition for this if you care about ordering
> (see
>
https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift#L299
)
> but then you can do
>
> var parts = values
> let mid = values.stablePartition { $0 % 2 == 0 }
> let divisibleByTwo = parts.prefix(upTo: mid)
> let notDivisibleByTwo = parts.suffix(from: mid)
>
> Nate Cook has an enhancement to the result of stablyPartitioned in that
> prototype that would let you write:
>
> let parts = values.stablyPartitioned { $0 % 2 == 0 }
> let divisibleByTwo = parts.prefix(upTo: parts.partitionPoint)
> let notDivisibleByTwo = parts.suffix(from: parts.partitionPoint)

Hmm, come to think of it, Nate, maybe there should also be a more
convenient way to get the two partitions from the result.

--
Dave

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


(Nate Cook) #7

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?

Well, you need a stable partition for this if you care about ordering
(see
https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift#L299)
but then you can do

var parts = values
let mid = values.stablePartition { $0 % 2 == 0 }
let divisibleByTwo = parts.prefix(upTo: mid)
let notDivisibleByTwo = parts.suffix(from: mid)

Nate Cook has an enhancement to the result of stablyPartitioned in that
prototype that would let you write:

let parts = values.stablyPartitioned { $0 % 2 == 0 }
let divisibleByTwo = parts.prefix(upTo: parts.partitionPoint)
let notDivisibleByTwo = parts.suffix(from: parts.partitionPoint)

Mine was for the result of the 'rotated' methods, but should work for the partitioning ones, too. It's not as clear to me what the benefit of the "lazy" partitioning in that Algorithm.swift is—wouldn't it be better to wrap a collection around two lazy filter sequences?

Here is a quick proof of concept of 'divided' and 'partitioned' methods: http://swiftlang.ng.bluemix.net/#/repl/57588cbda79b317716f02e04

Hmm, come to think of it, Nate, maybe there should also be a more
convenient way to get the two partitions from the result.

Definitely!

Nate

···

On Jun 8, 2016, at 3:40 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:
on Wed Jun 08 2016, Dave Abrahams <swift-evolution@swift.org> wrote:

on Wed Jun 08 2016, gadiraju praneeth <swift-evolution@swift.org> wrote:

--
Dave

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


(Dave Abrahams) #8

I added an extension to do this, something like this:

extension Array {

    func filterSplit(includeElement: (Element) -> Bool) -> ([Element],
[Element]) {

        var elementsSatisfyingCondition = [Element]()

        var elementsNotSatisfyingCondition = [Element]()

        self.forEach { element in

            if includeElement(element)
{ elementsSatisfyingCondition.append(element) }

            else { elementsNotSatisfyingCondition.append(element) }

        }

        return (elementsSatisfyingCondition, elementsNotSatisfyingCondition)

    }

}

that way you can right away do: values.filterSplit {
<yourPredicateBlock> }

Yes, it's convenient. Its efficiency is suboptimal, though, unless you
really need the results to be Arrays (rather than, say ArraySlices).

···

on Wed Jun 08 2016, gadiraju praneeth <praneethgadiraju-AT-gmail.com> wrote:

On Wed, Jun 8, 2016 at 3:40 PM, Dave Abrahams via swift-evolution < > swift-evolution@swift.org> wrote:

on Wed Jun 08 2016, Dave Abrahams <swift-evolution@swift.org> wrote:

> on Wed Jun 08 2016, gadiraju praneeth <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?
>
> Well, you need a stable partition for this if you care about ordering
> (see
>
https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift#L299
)
> but then you can do
>
> var parts = values
> let mid = values.stablePartition { $0 % 2 == 0 }
> let divisibleByTwo = parts.prefix(upTo: mid)
> let notDivisibleByTwo = parts.suffix(from: mid)
>
> Nate Cook has an enhancement to the result of stablyPartitioned in that
> prototype that would let you write:
>
> let parts = values.stablyPartitioned { $0 % 2 == 0 }
> let divisibleByTwo = parts.prefix(upTo: parts.partitionPoint)
> let notDivisibleByTwo = parts.suffix(from: parts.partitionPoint)

Hmm, come to think of it, Nate, maybe there should also be a more
convenient way to get the two partitions from the result.

--
Dave

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

--
Dave


(Dave Abrahams) #9

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?

Well, you need a stable partition for this if you care about ordering
(see
https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift#L299)
but then you can do

var parts = values
let mid = values.stablePartition { $0 % 2 == 0 }
let divisibleByTwo = parts.prefix(upTo: mid)
let notDivisibleByTwo = parts.suffix(from: mid)

Nate Cook has an enhancement to the result of stablyPartitioned in that
prototype that would let you write:

let parts = values.stablyPartitioned { $0 % 2 == 0 }
let divisibleByTwo = parts.prefix(upTo: parts.partitionPoint)
let notDivisibleByTwo = parts.suffix(from: parts.partitionPoint)

Mine was for the result of the 'rotated' methods, but should work for
the partitioning ones, too. It's not as clear to me what the benefit
of the "lazy" partitioning in that Algorithm.swift is

Just to pass “laziness” on from the result, so further computations can
also be lazy.

—wouldn't it be better to wrap a collection around two lazy filter
sequences?

Perhaps something like a
LazyFlatMap<CollectionOfTwo<LazyFilterCollection>> would be better, but
I have the concern that this would evaluate the predicate 2N times for
each traversal.

···

on Wed Jun 08 2016, Nate Cook <natecook-AT-gmail.com> wrote:

On Jun 8, 2016, at 3:40 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:
on Wed Jun 08 2016, Dave Abrahams <swift-evolution@swift.org> wrote:

on Wed Jun 08 2016, gadiraju praneeth <swift-evolution@swift.org> wrote:

Here is a quick proof of concept of 'divided' and 'partitioned'
methods:
http://swiftlang.ng.bluemix.net/#/repl/57588cbda79b317716f02e04

Hmm, come to think of it, Nate, maybe there should also be a more
convenient way to get the two partitions from the result.

Definitely!

Nate

--
Dave

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

--
Dave


(gadiraju praneeth) #10

Its values.filterSplit { $0 % 2 == 0 } in this case

···

On Wed, Jun 8, 2016 at 3:59 PM, gadiraju praneeth < praneethgadiraju@gmail.com> wrote:

I added an extension to do this, something like this:

extension Array {

    func filterSplit(includeElement: (Element) -> Bool) -> ([Element],
[Element]) {

        var elementsSatisfyingCondition = [Element]()

        var elementsNotSatisfyingCondition = [Element]()

        self.forEach { element in

            if includeElement(element)
{ elementsSatisfyingCondition.append(element) }

            else { elementsNotSatisfyingCondition.append(element) }

        }

        return
(elementsSatisfyingCondition, elementsNotSatisfyingCondition)

    }

}

that way you can right away do: values.filterSplit { <yourPredicateBlock> }

On Wed, Jun 8, 2016 at 3:40 PM, Dave Abrahams via swift-evolution < > swift-evolution@swift.org> wrote:

on Wed Jun 08 2016, Dave Abrahams <swift-evolution@swift.org> wrote:

> on Wed Jun 08 2016, gadiraju praneeth <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?
>
> Well, you need a stable partition for this if you care about ordering
> (see
>
https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift#L299
)
> but then you can do
>
> var parts = values
> let mid = values.stablePartition { $0 % 2 == 0 }
> let divisibleByTwo = parts.prefix(upTo: mid)
> let notDivisibleByTwo = parts.suffix(from: mid)
>
> Nate Cook has an enhancement to the result of stablyPartitioned in that
> prototype that would let you write:
>
> let parts = values.stablyPartitioned { $0 % 2 == 0 }
> let divisibleByTwo = parts.prefix(upTo: parts.partitionPoint)
> let notDivisibleByTwo = parts.suffix(from: parts.partitionPoint)

Hmm, come to think of it, Nate, maybe there should also be a more
convenient way to get the two partitions from the result.

--
Dave

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


(gadiraju praneeth) #11

I implemented something similar with two filters initially, but because of
2N vs N I changed it

···

On Wednesday, June 8, 2016, Dave Abrahams via swift-evolution < swift-evolution@swift.org> wrote:

on Wed Jun 08 2016, Nate Cook <natecook-AT-gmail.com> wrote:

>> On Jun 8, 2016, at 3:40 PM, Dave Abrahams via swift-evolution < > swift-evolution@swift.org <javascript:;>> wrote:
>>
>>
>> on Wed Jun 08 2016, Dave Abrahams <swift-evolution@swift.org > <javascript:;>> wrote:
>>
>
>>> on Wed Jun 08 2016, gadiraju praneeth <swift-evolution@swift.org > <javascript:;>> 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?
>>>
>>> Well, you need a stable partition for this if you care about ordering
>>> (see
>>>
https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift#L299
)
>>> but then you can do
>>>
>>> var parts = values
>>> let mid = values.stablePartition { $0 % 2 == 0 }
>>> let divisibleByTwo = parts.prefix(upTo: mid)
>>> let notDivisibleByTwo = parts.suffix(from: mid)
>>>
>>> Nate Cook has an enhancement to the result of stablyPartitioned in that
>>> prototype that would let you write:
>>>
>>> let parts = values.stablyPartitioned { $0 % 2 == 0 }
>>> let divisibleByTwo = parts.prefix(upTo: parts.partitionPoint)
>>> let notDivisibleByTwo = parts.suffix(from: parts.partitionPoint)
>
> Mine was for the result of the 'rotated' methods, but should work for
> the partitioning ones, too. It's not as clear to me what the benefit
> of the "lazy" partitioning in that Algorithm.swift is

Just to pass “laziness” on from the result, so further computations can
also be lazy.

> —wouldn't it be better to wrap a collection around two lazy filter
> sequences?

Perhaps something like a
LazyFlatMap<CollectionOfTwo<LazyFilterCollection>> would be better, but
I have the concern that this would evaluate the predicate 2N times for
each traversal.

> Here is a quick proof of concept of 'divided' and 'partitioned'
> methods:
> http://swiftlang.ng.bluemix.net/#/repl/57588cbda79b317716f02e04
>
>> Hmm, come to think of it, Nate, maybe there should also be a more
>> convenient way to get the two partitions from the result.
>
> Definitely!
>
> Nate
>
>> --
>> Dave
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <javascript:;>
>> https://lists.swift.org/mailman/listinfo/swift-evolution

--
Dave
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <javascript:;>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Thorsten Seitz) #12

+1 from me for adding this method to the standard library.
I would prefer the name `partition(by:)` for it, though, under which I know it from other languages and which is quite fitting, I think.

-Thorsten

···

Am 08.06.2016 um 22:59 schrieb gadiraju praneeth via swift-evolution <swift-evolution@swift.org>:

I added an extension to do this, something like this:
extension Array {
    func filterSplit(includeElement: (Element) -> Bool) -> ([Element], [Element]) {
        var elementsSatisfyingCondition = [Element]()
        var elementsNotSatisfyingCondition = [Element]()
        
        self.forEach { element in
            if includeElement(element) { elementsSatisfyingCondition.append(element) }
            else { elementsNotSatisfyingCondition.append(element) }
        }
        
        return (elementsSatisfyingCondition, elementsNotSatisfyingCondition)
    }
}

that way you can right away do: values.filterSplit { <yourPredicateBlock> }

On Wed, Jun 8, 2016 at 3:40 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Wed Jun 08 2016, Dave Abrahams <swift-evolution@swift.org> wrote:

> on Wed Jun 08 2016, gadiraju praneeth <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?
>
> Well, you need a stable partition for this if you care about ordering
> (see
> https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift#L299)
> but then you can do
>
> var parts = values
> let mid = values.stablePartition { $0 % 2 == 0 }
> let divisibleByTwo = parts.prefix(upTo: mid)
> let notDivisibleByTwo = parts.suffix(from: mid)
>
> Nate Cook has an enhancement to the result of stablyPartitioned in that
> prototype that would let you write:
>
> let parts = values.stablyPartitioned { $0 % 2 == 0 }
> let divisibleByTwo = parts.prefix(upTo: parts.partitionPoint)
> let notDivisibleByTwo = parts.suffix(from: parts.partitionPoint)

Hmm, come to think of it, Nate, maybe there should also be a more
convenient way to get the two partitions from the result.

--
Dave

_______________________________________________
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


(gadiraju praneeth) #13

Agree with the name. Also, the implementation could be better at Sequence
level rather than specific to Array, just like filter

···

On Wed, Jun 8, 2016 at 11:54 PM, Thorsten Seitz <tseitz42@icloud.com> wrote:

+1 from me for adding this method to the standard library.
I would prefer the name `partition(by:)` for it, though, under which I
know it from other languages and which is quite fitting, I think.

-Thorsten

Am 08.06.2016 um 22:59 schrieb gadiraju praneeth via swift-evolution < > swift-evolution@swift.org>:

I added an extension to do this, something like this:

extension Array {

    func filterSplit(includeElement: (Element) -> Bool) -> ([Element],
[Element]) {

        var elementsSatisfyingCondition = [Element]()

        var elementsNotSatisfyingCondition = [Element]()

        self.forEach { element in

            if includeElement(element)
{ elementsSatisfyingCondition.append(element) }

            else { elementsNotSatisfyingCondition.append(element) }

        }

        return
(elementsSatisfyingCondition, elementsNotSatisfyingCondition)

    }

}

that way you can right away do: values.filterSplit { <yourPredicateBlock> }

On Wed, Jun 8, 2016 at 3:40 PM, Dave Abrahams via swift-evolution < > swift-evolution@swift.org> wrote:

on Wed Jun 08 2016, Dave Abrahams <swift-evolution@swift.org> wrote:

> on Wed Jun 08 2016, gadiraju praneeth <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?
>
> Well, you need a stable partition for this if you care about ordering
> (see
>
https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift#L299
)
> but then you can do
>
> var parts = values
> let mid = values.stablePartition { $0 % 2 == 0 }
> let divisibleByTwo = parts.prefix(upTo: mid)
> let notDivisibleByTwo = parts.suffix(from: mid)
>
> Nate Cook has an enhancement to the result of stablyPartitioned in that
> prototype that would let you write:
>
> let parts = values.stablyPartitioned { $0 % 2 == 0 }
> let divisibleByTwo = parts.prefix(upTo: parts.partitionPoint)
> let notDivisibleByTwo = parts.suffix(from: parts.partitionPoint)

Hmm, come to think of it, Nate, maybe there should also be a more
convenient way to get the two partitions from the result.

--
Dave

_______________________________________________
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