在没有默认值的情况下有效地聚合非选项数组



我需要有效地聚合一个非可选值的数组,知道它的大小,有办法获得它的值,但没有默认值。

下面是一个相当合成的例子,类似于我所需要的。它不会编译,但它会给你一个想法:

public func array<A>( count: Int, getValue: () -> A ) -> Array<A> {
  var array = [A](count: count, repeatedValue: nil as! A)
  var i = 0
  while (i < count) {
    array[i] = getValue()
    i++
  }
  return array
}

请注意,类型Array<A?>的结果不起作用,我需要非可选项。还要注意,该解决方案必须高效,不能进行任何额外的遍历。

您可以使用添加数组元素的append()方法:

public func array<A>(count: Int, @noescape getValue: () -> A) -> [A] {
    var array = [A]()
    array.reserveCapacity(count)
    for _ in 0 ..< count {
        array.append(getValue())
    }
    return array
}

@noescape属性告诉编译器传递的闭包不存在函数调用,这允许一些性能优化,比较Swift 1.2中的@noescape属性。

但使用CollectionType:的map()方法更容易

/// Return an `Array` containing the results of mapping `transform`
/// over `self`.
///
/// - Complexity: O(N).
@warn_unused_result
public func map<T>(@noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]

在您的情况下:

public func array<A>(count: Int, @noescape getValue: () -> A) -> [A] {
    let array = (0 ..< count).map { _ in getValue() }
    return array
}

这里map()变换范围0中的每个整数。。。count-1到数组元素。闭包中的下划线表示未使用其参数(当前索引)。

我让你检查一下哪种方法更快。

示例用法:

let a = array(10) { arc4random_uniform(10) }
print(a) // [3, 7, 9, 4, 2, 3, 1, 5, 9, 7] (Your output may be different :-)

最新更新