我有两个带浮点数的大(数千个值)数组,并希望将它们组合在一个xy点数组中以便进一步处理,例如绘制。
现在,在Xcode游乐场,我正在这样做:
let xArray = // read from datafile, fast
let yArray = // read from another datafile, fast
struct xyPoint {
let x: Float
let y: Float
}
var spectrum: [xyPoint] = []
for i in 0..<xArray.count {
let xy = xyPoint(x: xArray[i], y: yArray[i])
spectrum.append(xy)
}
现在,当我在操场上跑步时,这需要很长时间。
我有什么想法可以加快速度吗?
答案 0 :(得分:3)
创建点数组的最简单方法是
let spectrum = zip(xArray, yArray).map(XYPoint.init)
(我冒昧地将结构XYPoint
称为Swift类型
应该以大写字母开头。)这也允许定义
结果数组为常量。
然而,就执行时间而言,它并不是最快的。 原因可能是
zip()
对一般序列进行操作,但不利用
输入是数组。zip()
返回Sequence
,因此map()
不知道要创建的元素的数量。
因此,目标阵列将重新分配几个
次。因此,如果您保留所需的显式循环,则更快 提前容量:
var spectrum: [XYPoint] = []
spectrum.reserveCapacity(xArray.count)
for i in 0..<xArray.count {
let xy = XYPoint(x: xArray[i], y: yArray[i])
spectrum.append(xy)
}
在我的测试中(在1.2 GHz Intel Core m5 MacBook上,在Release中编译) 模式)有两个10,000个元素的数组,第一个方法 大约0.65毫秒,第二种方法大约0.42毫秒。 对于1,000,000个元素,我测量了12毫秒而不是6毫秒。
答案 1 :(得分:2)
一旦你有两个独立的阵列,将它们组合起来有点尴尬,并且没有一个整洁的“Swifty”方法来做到这一点。如果你有一个结构数组,其中每个结构包含一个x和y值,你可以使用map
语句将该数组转换为一个CGPoint对象数组(实际上是另一个结构类型)。
你首先告诉我们:
let xArray = // read from datafile, fast
let yArray = // read from another datafile, fast
重做那些你没有显示的代码可能会更好,这样你就不用读取所有的x点数据文件,而是读取所有的y点数据文件:
CGPoint
值甚至,重构您创建数据文件的代码,以便它写入包含X / Y对数组的文件,而不是2个单独的文件。
如果你有两个独立的数组,你可以使用for ... in的变体为你提供索引和每个数组条目的值:
let xArray: [CGFloat] = [0.1, 0.2, 0.3, 0.4]
let yArray: [CGFloat] = [0.4, 0.3, 0.2, 0.1]
var output = [CGPoint]()
output.reserveCapacity(xArray.count)
for (index, value) in xArray.enumerated() {
let yValue = yArray[index]
let aPoint = CGPoint (x: value, y: yValue)
output.append(aPoint)
}
如果yArray
的值低于xArray
,则上述代码会崩溃,如果yArray
包含更多值,则会遗漏xArray
中的最后一个值{1}}。完整的实现应该首先进行错误检查,并处理数据具有不同数量值的情况。
答案 2 :(得分:2)
我检查了您的问题的各种解决方案的性能。您可以从this link to github
下载我的测试var spectrum: [XYPoint] = []
for i in 0..<xArray.count {
let xy = XYPoint(x: xArray[i], y: yArray[i])
spectrum.append(xy)
}
let spectrumB = zip(xArray, yArray).map(XYPoint.init)
let spectrum = (0 ..< xArray.count).map { i in
return XYPoint(x: xArray[i], y: yArray[i])
}
var spectrum: [XYPoint] = []
spectrum.reserveCapacity(xArray.count)
for (index, value) in xArray.enumerated() {
spectrum.append(XYPoint(x: xArray[index], y: yArray[index]))
}
╭──────────────┬──────────────┬──────────────┬──────────────╮
│ A │ B │ C │ D │
╭───────────╬══════════════╪══════════════╪══════════════╪══════════════╡
│ 100 ║ 0.000009426 │ 0.000002401 │ 0.000000571 │ 0.000000550 │
│ 200 ║ 0.000003356 │ 0.000002629 │ 0.000000911 │ 0.000000866 │
│ 500 ║ 0.000005610 │ 0.000007288 │ 0.000002236 │ 0.000002012 │
│ 1000 ║ 0.000010638 │ 0.000009181 │ 0.000003905 │ 0.000005030 │
│ 2000 ║ 0.000019377 │ 0.000013316 │ 0.000007116 │ 0.000008732 │
│ 5000 ║ 0.000023430 │ 0.000019304 │ 0.000019809 │ 0.000019092 │
│ 10000 ║ 0.000050463 │ 0.000031669 │ 0.000035121 │ 0.000035420 │
│ 20000 ║ 0.000087040 │ 0.000058664 │ 0.000069300 │ 0.000069456 │
│ 50000 ║ 0.000272357 │ 0.000204213 │ 0.000176962 │ 0.000192996 │
│ 100000 ║ 0.000721436 │ 0.000459551 │ 0.000415024 │ 0.000437604 │
│ 200000 ║ 0.001114534 │ 0.000924621 │ 0.000816374 │ 0.000896202 │
│ 500000 ║ 0.002576687 │ 0.002094998 │ 0.001860833 │ 0.002060462 │
│ 1000000 ║ 0.007063596 │ 0.005924892 │ 0.004319181 │ 0.004869024 │
│ 2000000 ║ 0.014474969 │ 0.013594134 │ 0.008568550 │ 0.009388957 │
│ 5000000 ║ 0.038348767 │ 0.035136008 │ 0.021276415 │ 0.023855382 │
│ 10000000 ║ 0.081750925 │ 0.078742713 │ 0.043578664 │ 0.047700495 │
│ 20000000 ║ 0.202616669 │ 0.199960563 │ 0.148141266 │ 0.145360923 │
│ 50000000 ║ 0.567078563 │ 0.552158644 │ 0.370327555 │ 0.397115294 │
│ 100000000 ║ 1.136993625 │ 1.101725386 │ 0.713406642 │ 0.740150322 │
└───────────╨──────────────┴──────────────┴──────────────┴──────────────┘
答案 3 :(得分:1)
当您在主操场文件中运行代码时,您可能已启用日志记录。这为代码增加了巨大的性能。
我在问题中尝试了你的代码作为一个函数。将函数放在主swift文件中,大小为10000的数组需要10分钟!
我将该函数移动到操场的sources文件夹中具有相同大小数组的单独swift文件,并立即完成。
我使用的代码来自您的问题(在func中),而不是优化版本。