Swift - 使用 where 子句在 for in 循环中取消包装可选项

16

我有一个包含可选成员的类:

class A {
    var i: Int? = nil
}

我有一个类型为 A 的对象数组。数组中的某些对象具有 i 的值,而其他一些对象则没有。

我想迭代数组中具有 i 值的对象,同时解开可选项。我找不到同时完成这两个操作的方法(甚至不知道是否可能),所以我被迫在循环内部编写一个 if let 结构。
例如:

// a1, a2 have a value for i
let arr: [A] = [a1, a2, a3]
for obj in arr where obj.i != nil {
    // I want to avoid if let, or force unwrapping here
    if let unwrapped = obj.i {
        print(i)
    }
    // let unwrapped = obj.i! ...
}

在Swift中是否可能?


1
在循环体中,你需要同时使用 obj 和(已解包的)obj.i 两个变量吗?还是说只需要 obj.i 就可以了? - Martin R
我确实需要在循环内使用obji这两个变量。 - Vince
3个回答

9

1.或许你可以使用flatMap方法来获取值i,然后将其打印出来。

arr.flatMap{ $0.i }.forEach{ print($0) }

2.或者尝试简单的守卫语句

arr.forEach { element in
    guard let i = element.i else { return }
    print(i)
}

flatMap 是处理这种事情的首选方式。请查看关于其优越性的文章 https://www.natashatherobot.com/swift-2-flatmap/ 。 - Maksym Musiienko
你的 flatMap(_:) 循环中只会返回 i,而不是同时返回 obji - Hamish

3
你可以使用case let语法,但没有map的帮助,结果不太易读:

您可以使用case let syntax,但是没有map的帮助,结果不太易读:

for case let .some(unwrapped) in arr.map(\.i) {
    print(unwrapped)
}

如果您正在转换外部对象,例如:

for case let object as String in arrayOfAny {
    if object.hasPrefix("tw") {
        print("Starts with 'tw'")
    }
}

改为:

for object in arrayOfAny where object is String {
    if object.hasPrefix("tw") { // Error: Value of type 'Any' has no member 'hasPrefix'
        print("Starts with 'tw'")
    }
}

1
这应该是答案,也可以这样写: for case let unwrapped? = arr { } - Mackarous

3
我认为这是不可能的。
即使你在循环中有一个where子句,obj的类型仍然是A类型,因此i仍然保持可选状态。
要理解这一点,考虑到你可以在循环内更改对象obj上的i值,所以编译器无法确定i的值是否有效,直到你将其解包。
你可以尝试类似以下的代码。
for obj in arr where obj.i != nil {
  guard let i = obj.i else { continue }

  print( i )
}

但如果你开始使用guard,你也可以跳过where子句

for obj in arr {
   guard let i = obj.i else { continue }

   print( i )
}

好的,我认为最好的方法是强制解包。我将循环中的 if let 视为 where 子句的重复。 - Vince
有些东西你可以使用,你可以使用 guard,你知道 guard 条件永远不会被触发,但你不需要在 if let 中包装你的代码。 - Radu Diță
我刚看到这个问题并发现了这篇文章,想着应该分享给未来的程序员们 :D https://medium.com/@rizwan95/swift-bit-3-unwrap-optional-values-using-for-in-loop-519e96b6f330 - ErickES7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接