为什么lazy
在这里使用?
extension SequenceType {
func mapSome<U>(transform: Generator.Element -> U?) -> [U] {
var result: [U] = []
for case let x? in lazy(self).map(transform) {
result.append(x)
}
return result
}
}
此扩展采用返回可选的转换函数,并返回仅包含未转换为nil的值的数组
为什么不使用self.map(transform)
?这里有懒惰吗?
答案 0 :(得分:11)
它避免了创建中间数组。
self.map(transform)
返回包含转换结果的数组 所有序列元素,然后遍历以构建 结果数组包含非零元素。
lazy(self).map(transform)
是转换元素的序列,然后是
迭代以获得非零元素。转化的元素
在枚举期间计算。 (每次致电next()
在惰性序列上通过转换下一个元素产生一个元素
原始序列的元素。)
两种方法都有效。惰性方法可能会表现得更好 对于大型序列,但这可能取决于许多因素(大小 对于数组,无论元素是值还是引用类型, 复制数组元素的成本是多少等)。适用于小型阵列 懒惰的方法可能会因为额外的而变慢 高架。在具体的应用程序中,使用Instruments进行分析 帮助决定使用哪种方法。
答案 1 :(得分:5)
正如Martin R所提到的那样lazy()
避免了中间数组的创建。但是,如果我将函数的执行时间与不同大小的数组进行比较,您会发现lazy()
“仅”加快了10%。
有趣的是,您发现lazy()
适用于少于200个元素的数组,速度快2倍,并且获得的元素数量几乎与没有转换的函数相同(快10%)。
(使用Xcode 6.4和Xcode 7测试,Playground中的全局函数和协议扩展为(已编译)源文件)
所以lazy()
宁愿用于Sequences
,你不知道它是否是有限的。然后,for循环可能与break
或return
:
for element in lazy(sequence).map{ ... } {
if element == 1000 {
break
}
// use element
}
如果你在无限Sequence
(如1,2,3 ......)上调用map,执行也将是无限的。使用lazy()
转换和执行得到“延迟”,因此如果你在最后一个元素之前突破循环,你可以更有效地处理“大”和无限序列。