I've written a lot of C++ but now I'm learning Swift. I did an exercise, the standard Sieve of Erastosthenes. It works fine, but it seems a bit clunky and I wonder if I'm missing some language features that might streamline it a bit and make it more idiomatic Swift.
Here's the code:
struct Sieve {
let primes: [Int]
init(_ maxValue: Int) {
var numbers = Array<Int?>(repeating: nil, count:maxValue + 1)
for n in 2...maxValue { numbers[n] = n }
var start = 2
while start < maxValue {
guard let prime = numbers.first(where: {$0 != nil && $0! >= start}) else {break}
let lo = 2 * prime!
if lo < maxValue {
for x in stride(from: lo, to: numbers.count, by: prime!) {
numbers[x] = nil
}
}
start = prime! + 1
}
primes = numbers.compactMap{$0}
}
}
With the line starting "guard let prime", I'd like to supply a starting index for the 'find' operation, which would be a lot more efficient and would let me drop the comparison $0! >= start
altogether. Something along the lines of
guard let prime = numbers.first(where: {$0 != nil}, start: start) else {break}
I also tried
guard let prime = (start...maxValue).first(where: {index in numbers[index] != nil}) else {break}
and that does work but it seems even more awkward. It does have the advantage of starting the search at the index start
instead of index zero each time. What's the preferred way to search an array beginning somewhere in the middle of it?