Swift for循环中的模式匹配

时间:2021-06-13 22:35:50

It seems like there should be a "Swiftier" way to do this - but I'm still wrapping my head around the various ways to do pattern matching in Swift.

似乎应该有一个“更快”的方法来做到这一点 - 但我仍然围绕着各种方式在Swift中进行模式匹配。

Suppose I have an Array of AnyObject and I'd like to loop through it and if the item is an Int AND the Int is a multiple of 5, then I'd like to print it out. Here's my initial approach that works:

假设我有一个AnyObject数组,我想循环遍历它,如果该项是Int并且Int是5的倍数,那么我想打印出来。这是我最初的方法:

let myStuff: [AnyObject] = [5, "dog", 11, 15, "cat"]

for item in myStuff {
    if let myInt = item as? Int where myInt % 5 == 0 {
        print ("\(item)")
    }
}

Honestly, that's not bad...but with all of Swift's pattern matching syntax, it seems like I should be able to consolidate the logic to 1 line. So far, I haven't found an approach that works - but I was expecting to be able to do something like:

老实说,这还不错......但是使用Swift的所有模式匹配语法,似乎我应该能够将逻辑合并到1行。到目前为止,我还没有找到一种有效的方法 - 但我希望能够做到这样的事情:

//This doesn't work, but I feel like something similar to this should
for item in myStuff where item is Int, item % 5 == 0 {
    print ("\(item)")
}

Obviously, this isn't a huge deal - but it's more a thought exercise for me to understand Swift's pattern matching a little better.

显然,这不是一个大问题 - 但对我来说,理解Swift的模式匹配更好一点是一种思考练习。

2 个解决方案

#1


8  

You can combine a pattern matching conditional cast with a where clause like so:

您可以将匹配条件转换的模式与where子句组合,如下所示:

let myStuff: [AnyObject] = [5, "dog", 11, 15, "cat"]

// item will be an Int, and divisible by 5
for case let item as Int in myStuff where item % 5 == 0 {
    print(item)
}

// Prints:
// 5
// 15

#2


6  

@Hamish's neat solution is, imho, the "optimal" one, and the one to be accepted. But for the sake of the discussion, as an alternative the somewhat same logic can be applied with a chained functional approach:

@Hamish的巧妙解决方案是,imho,“最佳”解决方案,以及被接受的解决方案。但是为了讨论,作为替代方案,可以使用链式功能方法应用稍微相同的逻辑:

let myStuff: [AnyObject] = [5, "dog", 11, 15, "cat"]

myStuff.flatMap{ $0 as? Int }.filter{ $0 % 5 == 0}.forEach {
    print($0)
} /* 5 15 */

#1


8  

You can combine a pattern matching conditional cast with a where clause like so:

您可以将匹配条件转换的模式与where子句组合,如下所示:

let myStuff: [AnyObject] = [5, "dog", 11, 15, "cat"]

// item will be an Int, and divisible by 5
for case let item as Int in myStuff where item % 5 == 0 {
    print(item)
}

// Prints:
// 5
// 15

#2


6  

@Hamish's neat solution is, imho, the "optimal" one, and the one to be accepted. But for the sake of the discussion, as an alternative the somewhat same logic can be applied with a chained functional approach:

@Hamish的巧妙解决方案是,imho,“最佳”解决方案,以及被接受的解决方案。但是为了讨论,作为替代方案,可以使用链式功能方法应用稍微相同的逻辑:

let myStuff: [AnyObject] = [5, "dog", 11, 15, "cat"]

myStuff.flatMap{ $0 as? Int }.filter{ $0 % 5 == 0}.forEach {
    print($0)
} /* 5 15 */