...或者如何在for循环条件中使用索引
嘿,伙计们 由于我们在swift 3中没有用于循环的c风格,我似乎无法找到一种方法来表达更复杂的循环,所以也许你可以帮助我。如果我要写这个
for(int i=5; num/i > 0; i*=5)
在swift 3中我该怎么做?
我来的关闭是:
for i in stride(from: 5, through: num, by: 5) where num/i > 0
但是,如果我是:5,25,125等,这当然会一次迭代5个块。
有什么想法吗?
由于
答案 0 :(得分:5)
使用辅助函数(最初在Converting a C-style for loop that uses division for the step to Swift 3定义)
public func sequence<T>(first: T, while condition: @escaping (T)-> Bool, next: @escaping (T) -> T) -> UnfoldSequence<T, T> {
let nextState = { (state: inout T) -> T? in
// Return `nil` if condition is no longer satisfied:
guard condition(state) else { return nil }
// Update current value _after_ returning from this call:
defer { state = next(state) }
// Return current value:
return state
}
return sequence(state: first, next: nextState)
}
你可以把循环写成
let num = 1000
for i in sequence(first: 5, while: { num/$0 > 0 }, next: { $0 * 5 }) {
print(i)
}
更简单的解决方案是while循环:
var i = 5
while num/i > 0 {
print(i)
i *= 5
}
但第一种解决方案的优点是循环变量的范围仅限于循环体,循环变量是常量。
Swift 3.1 将提供prefix(while:)
method for sequences,
然后不再需要辅助函数:
let num = 1000
for i in sequence(first: 5, next: { $0 * 5 }).prefix(while: { num/$0 > 0 }) {
print(i)
}
以上所有解决方案都与给定的C循环“等效”。
然而,如果num
接近Int.max
,它们都会崩溃
并且$0 * 5
溢出。如果这是一个问题,那么你必须检查
如果$0 * 5
在进行乘法之前适合整数范围。
实际上,这使得循环更简单 - 至少如果我们假设那样
num >= 5
以便循环至少执行一次:
for i in sequence(first: 5, next: { $0 <= num/5 ? $0 * 5 : nil }) {
print(i)
}
答案 1 :(得分:1)
为了完整性:while
循环方法的替代方法是使用AnyIterator
:
let num = 1000
var i = 5
for i in AnyIterator<Int>({
return i <= num ? { defer { i *= 5 }; return i }() : nil
}) {
// note that we choose to shadow the external i variable name,
// such that any access to i within this loop will only refer
// to the loop local immutable variable i.
print(i)
// e.g. i += 1 not legal, i refers to a constant here!
} /* 5
25
125
625 */
此方法与while
循环具有相同的缺点,因为循环“外部”i
变量在循环块的范围之外和之后存在。但是,此外部i
变量不是可在循环体中访问的i
变量,因为我们让循环体变量i
影响外部变量,从而限制对{{}的访问1}}在body体内的不可变,临时(loop scope local)之一。