Swift 4.2中的快速数组比较

时间:2019-03-02 04:32:20

标签: swift swift4.2

我有两个包含11059200个元素的整数数组。在下面的示例中,

我正在通过比较d1中元素的索引来将数组d2的值更改为0

以下程序的计算时间为

Comparing started: 2019-03-02 08:45:56 +0000
Comparing finished: 2019-03-02 08:46:00 +0000

此过程花费了4秒钟的时间。

我想减少时间。有没有可能?谢谢

var d1 = [Int]()
var d2 = [Int]()

let value = 11059200

for _ in 0...value{

    d1.append(Int.random(in: 0...value))
    d2.append(Int.random(in: 0...value))
}

print("Comparing started: \(Date())")

var _ = d1.enumerated().compactMap { (index,value) -> Int in

    return d2[index] == value ? 0 : value
}

print("Comparing finished: \(Date())")

更新

根据亚历山大的评论,我正在使用地图将时间从2-3秒减少

var _ = d1.enumerated().map { (index,value) -> Int in
  return d2[index] == value ? 0 : value
}

1 个答案:

答案 0 :(得分:1)

您可以通过使用简单的地图而不是compactMap来加快速度。您没有返回Optional(某种),因此您无需使用compactMap。实际上,您的表达式d2 [index] == value? 0:将值隐式提升为可选值,仅是为了使compactMap不得不花时间解开它。

另外,您可以使用zip来迭代两个序列,从而简化代码:

import Foundation

func printTimeElapsedWhenRunningCode(title: String, operation: () -> Void) {
    let startTime = CFAbsoluteTimeGetCurrent()
    operation()
    let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
    print("Time elapsed for \(title): \(timeElapsed) s.")
}

let max = 11059200

let d1 = (0...max).map { _ in Int.random(in: 0...max) }
let d2 = (0...max).map { _ in Int.random(in: 0...max) }

printTimeElapsedWhenRunningCode(title: "Enumerating and indexing, comparing using compactMap (original)") {
    let result = d1.enumerated().compactMap { index, value -> Int in
        return d2[index] == value ? 0 : value
    }

    print(result.count)
}

printTimeElapsedWhenRunningCode(title: "Enumerating and indexing, comparing using map") {
    let result = d1.enumerated().map { index, value -> Int in
        return d2[index] == value ? 0 : value
    }

    print(result.count)
}

// just for a benchmark, don't write codel like this.
printTimeElapsedWhenRunningCode(title: "Manual Indexing") {
    var result = Array<Int>()
    result.reserveCapacity(d1.count)
    for i in d1.indices {
        let (d1Value, d2Value) = (d1[i], d2[i])
        let newValue = d1Value == d2Value ? 0 : d1Value
        result.append(newValue)
    }

    print(result.count)
}

// "Best" from a readibility stand-point
printTimeElapsedWhenRunningCode(title: "Zip") {
    let result = zip(d1, d2).map { d1Value, d2Value in
        return d1Value == d2Value ? 0 : d1Value
    }

    print(result.count)
}

以下是未优化构建的初步结果。这些是 绝对没有意义的 。调试版本的目的是使编译器在尽可能短的时间内生成正确的,可运行的程序,而对性能的关注绝对为0。这对于快速的开发迭代非常有用,但对基准测试毫无用处。

  

枚举和建立索引所花费的时间,使用compactMap(原始)进行比较:6.206556916236877 s。

     

手动分度耗时:0.3380240201950073 s。

     

邮编经过的时间:7.123739957809448 s。

     

枚举和建立索引所花费的时间,使用地图进行比较:5.2529460191726685 s。

当您打开优化功能时(-O cli中的swiftc标志,或者作为Xcode构建目标中的一个选项),您将得到一张完全不同的图片:

  

枚举和建立索引所花费的时间,使用compactMap(原始)进行比较:0.5904990434646606 s。

     

枚举和建立索引所花费的时间,使用地图进行比较:0.22207605838775635 s。

     

经过手动索引处理的时间:0.18644499778747559 s。

     

邮编经过的时间:0.2339940071105957 s。

我建议您使用基于zip的方法,以提高其可读性。如果性能是绝对关键的,直到您确定可以牺牲微小的速度特权的可读性和可维护性,那么可能值得切换到手动索引,但这不太可能就是这种情况。