[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