【问题标题】:Refactor for-loop statement to swift 3.0将 for-loop 语句重构为 swift 3.0
【发布时间】:2016-07-13 14:35:43
【问题描述】:

我的代码中有以下行:

for (i = 0, j = count - 1; i < count; j = i++)

谁能帮忙删除i++ will be removed in Swift 3.0C-style for statement is depreciated这两个编译器警告?

【问题讨论】:

标签: swift


【解决方案1】:

你可以用这个:

var j = count-1
for i in 0..<count {
    defer { j = i } // This will keep the cycle "logic" all together, similarly to "j = i++"

    // Cycle body
}

编辑

正如@t0rst 所说,使用defer 时要小心,因为无论其封闭范围如何退出,它都会被执行,因此它不是100% 的替代品。

因此,虽然标准for ( forInit ; forTest ; forNext ) { … }在循环内出现break 语句、return 或异常情况下执行forNext,但defer 将。

Read here for more

【讨论】:

  • 很好地使用defer
  • ⚠️ 注意:defer 用于安全清理,因此无论其封闭范围如何退出都会执行。将 for ( forInit ; forTest ; forNext ) { … } 替换为 forInit; while forTest { defer { forNext } … } 将产生不同的行为:a) 当您从循环中中断时执行 defer 块,因此您的迭代器变量的状态不再与满足循环退出条件时相同,并且 b ) 如果您通过异常退出,则会执行 defer 块,这在您的 forNext 语句有副作用的不太可能的情况下会成为问题。
  • @t0rst 确实如此,但当然您不必在不了解其含义的情况下盲目地复制和粘贴代码。这只是您工具箱中的另一个工具,在大多数情况下,它是一个干净而优雅的解决方案。
  • @AlessandroOrrù re:“盲目地复制和粘贴代码而不理解它的含义”——你希望每个人都能理解吗?统计上不太可能。良好的结构可以减少认知负担,并且不需要开发人员对错误保持高度警惕,而不是现在。如果没有我上面的警告评论,普通读者可能会认为defer 会做他们想做的事——有些人会仔细检查,有些人不会,并且在很久以前忘记使用defer 之前可能不会出现错误场景。 defer 在这里不是一个“干净”的解决方案——你必须小心使用和记录它。
  • @t0rst 抱歉,这并不是针对。这是一个普遍的警告:永远不要盲目地复制代码,尤其是这样的简单行,而不理解它的含义。必须谨慎使用针对此问题或其他问题的每个“解决方案”。无论如何,我都会编辑我的原始帖子以添加有关效果的注释。
【解决方案2】:

或者,让我们疯狂地避免将j 声明为循环范围的外部!

片段 1

let count = 10

for (i, j) in [count-1..<count, 0..<count-1].flatten().enumerate() {
    print(i, j)
}
/* 0 9
   1 0
   2 1
   3 2
   4 3
   5 4
   6 5
   7 6
   8 7
   9 8 */

片段 2

for (i, j) in (-1..<count-1).map({ $0 < 0 ? count-1 : $0 }).enumerate() {
    print(i, j)
}

【讨论】:

  • 我的解决方案更疯狂:D
  • @appzYourLife 我觉得有必要升级;)
【解决方案3】:

试图赢得这个帖子中最疯狂的解决方案的奖

片段 1

extension Int {
    func j(count:Int) -> Int {
        return (self + count - 1) % count
    }
}

for i in 0..<count {
    print(i, i.j(count))
}

片段 2

let count = 10
let iList = 0..<count
let jList = iList.map { ($0 + count - 1) % count }

zip(iList, jList).forEach { (i, j) in
    print(i, j)
}

【讨论】:

  • 除了评论之外,我什至不会以任何其他形式发布彻底升级的 sn-p #3 :) for (i, j) in (1-count..&lt;count-1).filter({ $0 % (count-1) &gt;= 0 }).map(abs).enumerate() { print(i, j) }
  • @dfri:我相信代码混淆工具几乎不会比 sn-p#3 做得更好:D
  • 我不得不从第一个 flatMap 版本重构它,以便编译器处理它(v.1;太复杂了 :D)。谢谢你的乐趣,我其实很喜欢你上面的 sn-p 1,扩展 ftw!
【解决方案4】:

您可以使用辅助函数将 j 的包装抽象为:

func go(count: Int, block: (Int, Int) -> ()) {
  if count < 1 { return }
  block(0, count - 1)
  for i in 1 ..< count {
    block(i, i - 1)
  }
}

【讨论】:

    猜你喜欢
    • 2016-07-05
    • 2018-04-07
    • 2021-04-18
    • 2013-09-02
    • 2018-04-16
    • 1970-01-01
    • 2019-03-11
    • 2016-04-08
    • 2021-07-31
    相关资源
    最近更新 更多