2015-11-13 21 views
0

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

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

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?>型不会做的结果是,我需要非自选。还要注意解决方案必须是有效的,它不能做任何额外的遍历。

回答

2

您可以通过使用 的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 属性告知通过关闭不活得比 函数调用编译器,这允许一些性能优化, 比较@noescape attribute in Swift 1.2

但它更容易使用的CollectionTypemap()方法:

/// 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 :-) 
+0

谢谢! 'reserveCapacity'和'append'方法的组合已经完成了我一直在寻找的事情。 –