使用预分配和随机访问分配,而不是重复地将元素附加到数组中
添加first = ... 和last = ... 行不会像重复附加 元素(并因此重复扩展您的数组)到尚未预分配的数组那样影响性能.如果您初始化数组 myarray 并使用随机访问 (myarray[i]) 分配滑动窗口字符串值,而不是使用 .append(...),您应该能够减少开销。
var first = string1.startIndex
var last = first.advancedBy(n, limit: string1.endIndex)
var myarray = [String](count: string1.characters.count-n,
repeatedValue: "")
for i in 0..<myarray.count {
myarray[i] = string1[first...last]
first = first.advancedBy(1)
last = first.advancedBy(n, limit: string1.endIndex)
}
基准测试
我已使用以下示例 string1 和 n 将上述修改后的解决方案与您自己的解决方案进行对比:
var string1 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce pretium diam at arcu suscipit, sed molestie mi rhoncus. Donec neque sapien, luctus ultricies ex sed, tristique auctor sem. Praesent varius ullamcorper nisi a commodo. Mauris eu rutrum enim, sit amet hendrerit velit. Curabitur iaculis neque ut tellus pretium, at convallis odio posuere. Integer ultricies diam ex, sit amet faucibus odio ultrices eu. Morbi tincidunt felis tellus, eget gravida est suscipit quis. Nam nunc ipsum, molestie sit amet neque at, aliquam maximus lacus. Sed bibendum massa a lorem eleifend, non eleifend felis commodo. Vivamus eget sem luctus, aliquam dolor nec, finibus diam. Morbi id justo vehicula, eleifend arcu nec, hendrerit neque. Donec ex ante, fringilla id rhoncus nec, porta id tortor. Donec dapibus nisl nibh, non posuere lacus egestas non. Duis massa quam, elementum sit amet volutpat eget, tincidunt sodales urna. Donec at congue ligula, a sollicitudin tortor."
string1 = string1+string1+string1 // 2880 characters
let n = 4
基准测试结果(使用this QuartzCore-based function 测量)
- 带有
for i in ...循环的预初始化数组解决方案:2.5s
-
.append(..) 带有while 循环的解决方案,如您的问题所示:32.5s
如果执行时间很重要,显然您会受益于预先初始化数组并使用随机访问分配而不是重复使用.append(..)。
最后,您可以问自己是否真的需要显式存储滑动窗口中的所有子字符串,或者是否足以存储与它们对应的范围。如果n 很大,上面的myarray 将包含大量重复字符/重叠子字符串。在这种情况下,您最好只保存一个Range<String.CharacterView.Index> 元素数组,它可以很容易地用于即时提取string1 的相关子字符串。例如:
var first = string1.startIndex
var last = first.advancedBy(n, limit: string1.endIndex)
var rangeArr = [Range<String.CharacterView.Index>](
count: string1.characters.count-n,
repeatedValue: first...last)
for i in 0..<rangeArr.count {
rangeArr[i] = first...last
first = first.advancedBy(1)
last = first.advancedBy(n, limit: string1.endIndex)
}