优化加入破折号长斯威夫特字符串
我试图把一个十六进制字符串,并插入所有其他角色之间的连字符(如“b201a968”到“b2-01-a9-68”)。我发现有几种方法可以做到这一点,但问题是我的字符串相当大(8066个字符),而且我能够最快速地运行它仍然需要几秒钟的时间。这些是我尝试过的方式,以及他们正在接受的时间。任何人都可以帮我优化这个功能吗?优化加入破折号长斯威夫特字符串
//42.68 seconds
func reformatDebugString(string: String) -> String
{
var myString = string
var index = 2
while(true){
myString.insert("-", at: myString.index(myString.startIndex, offsetBy: index))
index += 3
if(index >= myString.characters.count){
break
}
}
return myString
}
//21.65 seconds
func reformatDebugString3(string: String) -> String
{
var myString = ""
let length = string.characters.count
var first = true
for i in 0...length-1{
let index = string.index(myString.startIndex, offsetBy: i)
let c = string[index]
myString += "\(c)"
if(!first){
myString += "-"
}
first = !first
}
return myString
}
//11.37 seconds
func reformatDebugString(string: String) -> String
{
var myString = string
var index = myString.characters.count - 2
while(true){
myString.insert("-", at: myString.index(myString.startIndex, offsetBy: index))
index -= 2
if(index == 0){
break
}
}
return myString
}
正如,你应该避免这两个东西:
- 计算每个指标与
string.index(string.startIndex, offsetBy: ...)
- 修改大字符串
insert(_:at:)
所以,这可以是另一个方式:
func reformatDebugString4(string: String) -> String {
var result = ""
var currentIndex = string.startIndex
while currentIndex < string.endIndex {
let nextIndex = string.index(currentIndex, offsetBy: 2, limitedBy: string.endIndex) ?? string.endIndex
if currentIndex != string.startIndex {
result += "-"
}
result += string[currentIndex..<nextIndex]
currentIndex = nextIndex
}
return result
}
与所有你的三个方法的问题是,为了获得当前字符的索引在循环使用index(_:offsetBy:)
。这是一个O(n)运算,其中n是偏移的距离 - 因此,所有三个函数都以二次方式运行。
此外,为了解决方案#1和#3,将插入到所得的字符串是一个为O(n)操作中,当将插入点之后的所有字符都被向上移动以容纳附加字符。在这种情况下,从头开始构建字符串通常会更便宜,因为我们可以在字符串的末尾添加给定字符,如果字符串具有足够的容量,则为O(1),否则为O(n)。
也为解决方案#1,说myString.characters.count
是O(n)的操作,所以你要在循环的每次迭代做不是。
所以,我们要从头开始构建的字符串,并避免索引和计算循环内的字符数。下面是这样做的一种方式:
extension String {
func addingDashes() -> String {
var result = ""
for (offset, character) in characters.enumerated() {
// don't insert a '-' before the first character,
// otherwise insert one before every other character.
if offset != 0 && offset % 2 == 0 {
result.append("-")
}
result.append(character)
}
return result
}
}
// ...
print("b201a968".addingDashes()) // b2-01-a9-68
您的最佳解决方案(#3)在一份新闻稿中构建了我的电脑上37.79s,上面的方法了0.023s。在哈米什的答案已经指出
简单,优雅,快速。 EZ PZ。 – NSGangster
@Hamish,我在下面的链接中分享了我的Xcode操场。在我的系统中,我的解决方案需要12.6秒左右,你的时间是20.5秒,而OOper的时间约为15.3秒。你可以试试你的系统吗? https://drive.google.com/open?id=0Bz423-2RSnjHMzlGbWNpQy1LSG8 –
@RyanTensmeyer不要使用游乐场 - 他们真的越野车和不可靠的。如果你的代码放到一个实际的项目(MacOS的命令行工具模板是一个很好的地方去),你应该可以看到正确的结果(另外,这是最好的标杆发布版本,以占编译器的优化 - 而还要确保编译器不会完全优化该方法)。 [这是我的基准代码](https://gist.github.com/hamishknight/d1e983e0445084cce314a50333a4d32e)。 – Hamish
这似乎是一个总理我们并行化的情况 - 尝试dispatch_apply,也许。 –