【问题标题】:Writing multiple nested for...in loops in Swift在 Swift 中编写多个嵌套的 for...in 循环
【发布时间】:2019-08-29 14:45:00
【问题描述】:

请在 Swift 中编写下面的嵌套 for...in 循环是否有更简洁或更好的方法?还是使用 for... 以正确的方式填充我的卡片?

for cardNumber in 1...3 {
    for cardSymbolIdentifier in 1...3 {
        for cardColorIdentifier in 1...3 {
            for cardShadingIdentifier in 1...3 {
                let card = Card(cardNumber: cardNumber, cardSymbolIdentifier: cardSymbolIdentifier, cardColorIdentifier: cardColorIdentifier, cardShadingIdentifier: cardShadingIdentifier)
                deckOfCards.append(card)
            }
        }
    }
}

它确实可以完成这项工作,但我在文档中找不到任何关于编写多个嵌套循环的内容。

提前非常感谢, 安迪

【问题讨论】:

  • 乍一看,这对于您的数据来说似乎是一个糟糕的结构。
  • 只是好奇:这是为了Set game 吗?
  • @MartinR 它可能是is。但这也使用嵌套的 for 循环。为避免它们,应生成所有可能的使用 1,2,3 的 4 元素数组(与 this 类似但不完全相同)
  • @RakeshaShastri 请问怎么样?我很想知道一种更好的方法。
  • 在我看来,您的嵌套循环非常适合您的需求:它们直截了当、易于阅读、易于维护,而且完全没有性能问题需要考虑。使用像 flatMap 等更复杂的函数通常会减少代码大小,但不会自动提高可读性。

标签: swift for-in-loop


【解决方案1】:

根据需要,您的代码完全没有优化问题,但您可以使其更优雅或更快捷(:p)

let values = [1,2,3]

values.forEach { (cardNumber) in
    values.forEach { (cardSymbolIdentifier) in
        values.forEach { (cardColorIdentifier) in
            values.forEach { (cardShadingIdentifier) in

                let card = Card(cardNumber: cardNumber, cardSymbolIdentifier: cardSymbolIdentifier, cardColorIdentifier: cardColorIdentifier, cardShadingIdentifier: cardShadingIdentifier)
                deckOfCards.append(card)
            }
        }
    }
}   

【讨论】:

  • 我不同意 forEach 更 Swifty。 for...in 是 Swift 中更强大、更一致、更灵活的构造。有时,核心团队的成员甚至建议删除forEach,因为它具有误导性行为并且是多余的。它的主要原因是提供 filtermap 的对称性(它在那里很有用),但它不应该用于替换简单的 for...in 循环 IMO。
  • 为什么不更进一步让它发挥作用,通过.append 删除突变并将.forEach 替换为.flatMap (除了在最内部的迭代中,应该使用.map 以及在哪里你直接返回你的Card)?
【解决方案2】:

您的 for 循环绝对没有问题。它们是优秀的、编写良好的 Swift。您的代码的唯一问题是它强制 deckOfCards 是可变的 (var),这 可能 是不可取的。如果是,您可以使用map,但我认为这不是特别好的 Swift,只是略有不同。

let d = (1...3).flatMap { number in
    (1...3).flatMap { symbol in
        (1...3).flatMap { color in
            (1...3).map { shading in
                Card.init(cardNumber: number,
                          cardSymbolIdentifier: symbol,
                          cardColorIdentifier: color,
                          cardShadingIdentifier: shading
                )}}}}

我会可能以第二种方式写它,但仅出于文体原因。你的 for 循环绝对没问题。


请注意下面@user28434 的评论。我的original version 有一个重大错误(它返回了错误的类型)。从 Swift 发布之日起,我就一直在编写它。我教斯威夫特。我用 Swift 教授 函数式编程。我在写的时候搞砸了。我永远不会用简单的 for 循环犯这个错误。那里有一个重要的教训。

【讨论】:

  • 它将是 [[[[Card]]]] 而不是平面 [Card]。需要一些扁平化。
  • 白痴mistakes的教训
【解决方案3】:

如果你在一个循环中这样做,那么它在算术上变得复杂

for i in 0..<81 {
    deckOfCards.append(
        Card(cardNumber: i / 27, cardSymbolIdentifier: i/9 % 3, 
             cardColorIdentifier: i/3 % 3, cardShadingIdentifier: i % 3)
    )
}

let deckOfCards = (0..<81).map {

    Card(cardNumber: $0 / 27, cardSymbolIdentifier: $0/9 % 3, 
         cardColorIdentifier: $0/3 % 3, cardShadingIdentifier: $0 % 3)
}

在这两个示例中 - 索引都从 0 开始,因此您的类初始化函数应该将索引移动一点

在每个参数中添加 +1之前/之后传递

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-15
    • 2021-03-13
    • 2014-11-05
    • 1970-01-01
    • 1970-01-01
    • 2017-08-13
    • 2019-05-30
    • 1970-01-01
    相关资源
    最近更新 更多