2017-06-02 91 views
3

我知道Swift的更高阶的函数,比如Map,Filter,Reduce和FlatMap,但我没有意识到任何类似于'All'或'Any'的返回布尔值的正面测试会短路的同时列举结果。Swift是否有像Any或All这样的高阶函数短路?

例如,考虑您拥有10,000个对象的集合,每个对象都有一个名为isFulfilled的属性,并且您想查看该集合中是否有isFulfilled设置为false。在C#中,您可以使用myObjects.Any(obj -> !obj.isFulfilled),并且在遇到该情况时,将会使枚举的其余部分短路并立即返回true

Swift中有这样的事吗?

回答

2

Sequence(并且特别是CollectionArray)具有以布尔谓词为参数的(短路)contains(where:)方法。例如,如果

if array.contains(where: { $0 % 2 == 0 }) 

检查该数组包含任何偶数。

没有“全部”方法,但是可以通过否定谓词和结果来使用以及 。例如,

if !array.contains(where: { $0 % 2 != 0 }) 

检查阵列中的所有数字是偶数。当然你也可以自定义一个扩展方法:

extension Sequence { 
    func allSatisfy(_ predicate: (Iterator.Element) -> Bool) -> Bool { 
     return !contains(where: { !predicate($0) }) 
    } 
} 

如果你想允许“扔”谓词以同样的方式作为 contains方法,然后将它定义为

extension Sequence { 
    func allSatisfy(_ predicate: (Iterator.Element) throws -> Bool) rethrows -> Bool { 
     return try !contains(where: { try !predicate($0) }) 
    } 
} 
3

另外一个在这种情况下,您可以在Swift中做的与“短路”类似的事情是使用集合的lazy属性,这会将您的实现更改为如下所示:

myObjects.lazy.filter({ !$0.isFulfilled }).first != nil 

这与你所要求的并不完全相同,但可能有助于在处理这些高阶函数时提供另一种选择。你可以阅读更多关于苹果的文档lazyhttps://developer.apple.com/reference/swift/array/1782542-lazy

+0

对于Array上的lazy属性的信息+1。我知道延迟执行直到查询时间的懒惰属性,但我不知道这个特定的'视图'到数组中。我喜欢!谢谢! – MarqueIV

0

如果你有这样的阵列中的所有对象,他们应该遵循的一些协议,它实现了可变isFulfilled ......你可以看到,你可以把这些对象confrom到(我们称之为履行协议)......现在,你可以在这里施展数组到类型[FulfilledItem] ...现在你可以继续作为一般

我粘贴代码为您更好地理解:

你看,你不能扩展任何或AnyObject,因为AnyObject是协议,不能被扩展(我猜想苹果打算),但你可以,子类“协议或只要你喜欢专业调用它 - 使协议从AnyObject继承...

protocol FulfilledItem: AnyObject{ 

    var isFulfilled: Bool {get set} 

} 

class itemWithTrueValue: FulfilledItem{ 
    var isFulfilled: Bool = true 
} 

class itemWithFalseValue: FulfilledItem{ 
    var isFulfilled: Bool = false 
} 

var arrayOfFulFilled: [FulfilledItem] = [itemWithFalseValue(),itemWithFalseValue(),itemWithFalseValue(),itemWithFalseValue(),itemWithFalseValue(),itemWithFalseValue()] 

    let boolValue = arrayOfFulFilled.contains(where: { 
     $0.isFulfilled == false 
    }) 

现在我们已经得到了自己一个非常好看的自定义协议继承所有的所有属性+我们美丽的isFulfilled财产,这是我们现在处理的通常...

根据苹果文档:

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html#//apple_ref/doc/uid/TP40014097-CH22-ID342

AnyObject仅供参考类型(类),任何对于两个值类型和引用类型,所以我想这是首选继承AnyObject ...

现在你投,而不是AnyObject到阵列协议项FulfilledItem,你将有漂亮的解决方案(不要忘记每一个项目,以符合该协议并将其值设置...)

祝快乐编码:)

+1

感谢您的回复,但您解决了错误的问题。我的问题是询问Swift中是否有任何短路高阶函数。我只是使用isFulfilled作为一个任意的例子。另外,如果我们谈论的是具有isFulfilled属性的具体类型的同类序列,则无论如何您都不会创建协议,因为您只需在对象上使用属性。我没有说,不管技术上你是否正确。尽管如此,具有讽刺意味的是,你的回答包括我以后的......'包含(其中:)以一种迂回的方式,你确实回答了它! :) – MarqueIV

相关问题