Reputation: 30043
I came to this:
for x in 1...(myArray.count - 1) { task() }
which is very ugly. Is there a better way?
Upvotes: 3
Views: 106
Reputation: 39040
Here's a way with Swift 2:
for x in myArray where x != myArray.first { task() }
Upvotes: 0
Reputation: 40963
You have to be a little careful, as if the array is empty, this will crash:
let a: [Int] = []
let range = 0..<a.count-1
// fatal error: Can't form Range with end < start
Strides don’t have this problem (since Strideable
things must be Comparable
) so you could do:
for _ in stride(from: 0, to: a.count - 1, by: 1) {
// will only execute if a.count > 2
print("blah")
}
Alternatively, if you guard it, you can use dropFirst
:
for _ in (a.isEmpty ? [] : dropFirst(a)) {
print("blah")
}
I would strongly advise against trying to make this look neater by creating a pseudo-for-loop that runs one less than the count times. There’s a reason that there’s no forEach
or repeat
functions in Swift. These kind of loops seem nice at first but there are lots of bugs that arise from them (for example, return
or continue
don’t work the way you might expect, also it’s generally considered bad practice to use a higher-order function to do external mutation – whereas a regular for
loop is a suggestion that mutation/side-effects are likely).
The neatest extension-type solution would probably be to extend Array
to do a safe drop-first:
extension Array {
// version of dropFirst that returns empty array for both
// empty and single-element array
func safeDropFirst() -> ArraySlice<T> {
return self.isEmpty ? [] : dropFirst(self)
}
}
for _ in myArray.safeDropFirst() {
doThing()
}
Upvotes: 5
Reputation: 60006
Not much better, but:
for _ in 1..<myArray.count { task() }
But this will crash if myArray
is empty (thanks, Airspeed Velocity).
If you happen to need that a lot for some reason, you can provide your own “loop abstraction” and take care of that issue too:
func repeatArray<T>(arr: [T], @noescape f: () -> Void) {
if !arr.isEmpty {
for _ in 1..<arr.count {
f()
}
}
}
repeatArray(myArray) {
task()
}
Upvotes: 4