Last active
January 31, 2019 14:45
-
-
Save jnutting/5a384fced8785727194c04cffc5b3b96 to your computer and use it in GitHub Desktop.
A short-circuiting compactMap for Swift's Sequence, that returns up to a maximum number of non-nil items
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Sequence's compactMap lets you transform one | |
* sequence of values into another, and strip | |
* out any nil results. Sometimes, all you want | |
* is the first non-nil result, and don't want | |
* to futher evaluate the transform for the | |
* remaining values in the original sequence. | |
* This lets you do that. | |
*/ | |
extension Sequence { | |
func compactMap<ElementOfResult>(first maximum: UInt, _ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult] { | |
var results = [ElementOfResult]() | |
for element in self { | |
if results.count >= maximum { break } | |
if let result = try transform(element) { | |
results.append(result) | |
} | |
} | |
return results | |
} | |
func compactMapFirst<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> ElementOfResult? { | |
return try compactMap(first: 1, transform).first | |
} | |
} | |
// Usage example: | |
let items = [1, 3, 7, 10, 15, 20, 21, 22, 23, 30, 34] | |
let transformTensMinusOne: (Int) -> Int? = { return $0 % 10 == 0 ? $0 - 1 : nil } | |
let tensMinusOne = items.compactMap(transformTensMinusOne) // -> [9, 19, 29] | |
let tensMinusOne_firstTwoArray = items.compactMap(first: 2, transformTensMinusOne) // -> [9, 19] | |
let tensMinusOne_firstOneArray = items.compactMap(first: 1, transformTensMinusOne) // -> [9] | |
let tensMinusOne_firstOne = items.compactMapFirst(transformTensMinusOne) // -> Optional(9) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment