Swift 3 for循环增量

use*_*990 40 swift swift3

如何在Swift3中编写以下内容?

for (f = first; f <= last; f += interval)          
{
    n += 1
}
Run Code Online (Sandbox Code Playgroud)

这是我自己的尝试

for _ in 0.stride(to: last, by: interval)
{
    n += 1
}
Run Code Online (Sandbox Code Playgroud)

dfr*_*fri 63

Swift 2.2 - > 3.0 Strideable::s stride(...)被全局stride(...)函数取代

在Swift 2.2中,我们可以(正如您自己尝试过的那样)使用blueprinted(和默认实现的)函数stride(through:by:)以及stride(to:by:) 协议Strideable

/* Swift 2.2: stride example usage */
let from = 0
let to = 10
let through = 10
let by = 1
for _ in from.stride(through, by: by) { } // from ... through (steps: 'by')
for _ in from.stride(to, by: by) { }      // from ..< to      (steps: 'by')
Run Code Online (Sandbox Code Playgroud)

而在雨燕3.0,这两个功能已移出Strideable有利于全局函数stride(from:through:by:)stride(from:to:by:) ; 因此,上面的等效Swift 3.0版本如下

/* Swift 3.0: stride example usage */
let from = 0
let to = 10
let through = 10
let by = 1
for _ in stride(from: from, through: through, by: by) { }
for _ in stride(from: from, to: to, by: by) { }
Run Code Online (Sandbox Code Playgroud)

在您的示例中,您希望使用闭合间隔步长替代stride(from:through:by:),因为for循环中的不变量使用比较小于或等于(<=).即

/* example values of your parameters 'first', 'last' and 'interval' */
let first = 0
let last = 10
let interval = 2
var n = 0
for f in stride(from: first, through: last, by: interval) { 
    print(f)
    n += 1 
} // 0 2 4 6 8 10
print(n) // 6
Run Code Online (Sandbox Code Playgroud)

其中,自然地,我们使用您的for仅环的通道从一个例子for环路stride,你可以自然地,为您具体的例子,只是计算n,而不需要一个循环的(n=1+(last-first)/interval).

Swift 3.0:stride更复杂的迭代增量逻辑的替代方案

随着演进提案SE-0094的实施,Swift 3.0引入了全局sequence功能:

stride对于具有更复杂的迭代增量关系的情况(这个例子中不是这种情况),它可以是一个合适的替代方案.

声明(S)

func sequence<T>(first: T, next: @escaping (T) -> T?) -> 
         UnfoldSequence<T, (T?, Bool)>

func sequence<T, State>(state: State, 
                        next: @escaping (inout State) -> T?) ->
           UnfoldSequence<T, State>
Run Code Online (Sandbox Code Playgroud)

我们将简要介绍这两个函数中的第一个.的next参数需要施加一些逻辑来懒惰地构造下一个序列元素给定当前一个(从闭合first).next返回时序列终止nil,如果next永不返回则终止序列nil.

应用于上面简单的常量步长示例,该sequence方法有点冗长,并且适用于此目的的stride解决方案:

let first = 0
let last = 10
let interval = 2
var n = 0
for f in sequence(first: first,
                  next: { $0 + interval <= last ? $0 + interval : nil }) {
    print(f)
    n += 1
} // 0 2 4 6 8 10
print(n) // 6
Run Code Online (Sandbox Code Playgroud)

sequence对于具有非恒定步幅的情况,这些函数非常有用,例如,如以下问答中所述的示例:

只需注意终止序列,最后nil返回(如果不是:"无限"元素生成),或者,当Swift 3.1到达时,将其懒惰生成与prefix(while:)序列方法结合使用,如进化提议SE-中所述0045.后者应用于该答案的运行示例使得该sequence方法不那么冗长,明显包括元素生成的终止标准.

/* for Swift 3.1 */
// ... as above
for f in sequence(first: first, next: { $0 + interval })
    .prefix(while: { $0 <= last }) {
    print(f)
    n += 1
} // 0 2 4 6 8 10
print(n) // 6
Run Code Online (Sandbox Code Playgroud)

  • 我们不是在 Swift 2 中远离全局函数,现在在 Swift 3 中返回它们吗?&lt;&lt;叹息&gt;&gt; (2认同)

Ima*_*tit 26

使用Swift 4.2,您可以选择以下5个示例中的一个来解决您的问题.


#1.使用stride(from:to:by:)功能

let first = 0
let last = 10
let interval = 2

let sequence = stride(from: first, to: last, by: interval)

for element in sequence {
    print(element)
}

/*
prints:
0
2
4
6
8
*/
Run Code Online (Sandbox Code Playgroud)

#2.使用sequence(first:next:)功能

let first = 0
let last = 10
let interval = 2

let unfoldSequence = sequence(first: first, next: {
    $0 + interval < last ? $0 + interval : nil
})

for element in unfoldSequence {
    print(element)
}

/*
prints:
0
2
4
6
8
*/
Run Code Online (Sandbox Code Playgroud)

#3.使用AnySequence init(_:)初始化程序

let anySequence = AnySequence<Int>({ () -> AnyIterator<Int> in
    let first = 0
    let last = 10
    let interval = 2

    var value = first
    return AnyIterator<Int> {
        defer { value += interval }
        return value < last ? value : nil
    }
})

for element in anySequence {
    print(element)
}

/*
prints:
0
2
4
6
8
*/
Run Code Online (Sandbox Code Playgroud)

#4.使用CountableRange filter(_:)方法

let first = 0
let last = 10
let interval = 2

let range = first ..< last
let lazyCollection = range.lazy.filter({ $0 % interval == 0 })

for element in lazyCollection {
    print(element)
}

/*
prints:
0
2
4
6
8
*/
Run Code Online (Sandbox Code Playgroud)

#5.使用CountableRange flatMap(_:)方法

let first = 0
let last = 10
let interval = 2

let range = first ..< last
let lazyCollection = range.lazy.compactMap({ $0 % interval == 0 ? $0 : nil })

for element in lazyCollection {
    print(element)
}

/*
prints:
0
2
4
6
8
*/
Run Code Online (Sandbox Code Playgroud)


Dan*_*ark 12

简单地说,Swift 3.0的工作代码:

let (first, last, interval) = (0, 100, 1)
var n = 0
for _ in stride(from: first, to: last, by: interval) {
    n += 1
}
Run Code Online (Sandbox Code Playgroud)


use*_*990 -5

for _ in 0.stride(to: 最后, by: 间隔) { n += 1 }

  • 在 Swift 3 中你不能说“0.stride”。 (4认同)