New 'partioned(by:)' method

Hi everyone,

Currently, we have a partition(by:) for MutableCollection, introduced by [Review] SE-0120: Revise 'partition' Method Signature in Swift 3.0.

It would be nice to introduce a non-mutable version called partioned(by:), to give functionality parity between mutable/non-mutable following the approach of other methods like sort(by:), sorted(by:), and to have a cleaner API when the developer is not working with a mutable collection, since for the latest, a local copy of a Collection needs to be maintained and accessed using the partition index, like the following code:

let numbers = [30, 40, 20, 30, 30, 60, 10]
var copyOfNumbers = numbers
let partitionIndex = copyOfNumbers.partition(by: { $0 > 30 })
let firstPartition = copyOfNumbers[..< partitionIndex]
let secondPartition = copyOfNumbers[partitionIndex...]

The concrete implementation of partioned(by:) would be pretty straight forward and it would return two partitions:

extension RangeReplaceableCollection {
    public func partitioned(by belongsInSecondPartition: (Element) throws -> Bool) rethrows -> (Self, Self) {
        var firstPartition = Self()
        var secondPartition = Self()
        for element in self {
            if try belongsInSecondPartition(element) {
                secondPartition.append(element)
            } else {
                firstPartition.append(element)
            }
        }

        return (firstPartition, secondPartition)
    }
}

Or more generic as an extension of Sequence:

extension Sequence {
    public func partitioned(by belongsInSecondPartition: (Element) throws -> Bool) rethrows -> ([Element], [Element]) {
        var firstPartition = [Element]()
        var secondPartition = [Element]()
        for element in self {
            if try belongsInSecondPartition(element) {
                secondPartition.append(element)
            } else {
                firstPartition.append(element)
            }
        }
        
        return (firstPartition, secondPartition)
    }
}

I researched a bit and other language like Kotlin have a similar method too: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/partition.html

Since it is my first pitch I hope I didn’t make any big mistakes or missed something, if so please pardon me :smile:
I also tried to search if something similar was already discussed in the past, this is what I found: Adding a new filter method which returns 2 arrays.

What do you think? Would it be worth to add? :slight_smile:

4 Likes

Would be more convenient to add it to Sequence, don’t you think? And return a pair of Arrays, following the approach to sorted(), which as well belongs to Sequence.

Yep :slight_smile: I just updated my original post, thanks!

1 Like

This seems uncontroversial and useful to me.

1 Like

I think this function, like filter after SE-0174, should return an associated type that would default to Array for Sequences and Self for RangeReplaceableCollection.