我有这个代码,并且花了很多时间在swift中执行? 每次迭代需要1秒才能执行,为什么?
执行该循环时的CPU百分比为97-98%,能源影响很高
这是代码
var braces:Int = 1;
var i:Int = startIndex;
let jsFileChars = Array(javascriptFile);
while(i < javascriptFile.count){ //count:1240265
if (braces == 0) {
break;
}
if (jsFileChars[i] == "{"){
braces = braces+1;
}else if (jsFileChars[i] == "}"){
braces = braces-1;
}
i = i+1;
}
这个循环以非常缓慢的速度迭代,为什么?
答案 0 :(得分:5)
循环很慢,因为确定Swift 字符串的count
是a
O(N)操作,其中N是字符串中的字符数。
另请参阅“Swift编程语言”中的Counting Characters:
请注意
扩展的字形集群可以由多个Unicode标量组成。这意味着不同的字符和相同字符的不同表示可能需要不同的内存量来存储。因此,Swift中的字符不会在字符串表示中占用相同数量的内存。因此,如果不迭代字符串以确定其扩展的字形集群边界,则无法计算字符串中的字符数。 ...
javascriptFile.count
取代jsFileChars.count
已经应该了
提高性能,因为数组的长度是确定的
恒定的时间。
更好地直接迭代字符,而不创建 数组:
var braces = 1
for char in javascriptFile {
if char == "{" {
braces += 1
} else if char == "}" {
braces -= 1
}
}
迭代UTF-16视图甚至更快,因为那样 是Swift字符串(当前)用作内部存储的东西:
let openingBrace = "{".utf16.first!
let closingBrace = "}".utf16.first!
var braces = 1
for char in javascriptFile.utf16 {
if char == openingBrace {
braces += 1
} else if char == closingBrace {
braces -= 1
}
}
答案 1 :(得分:2)
如果你想在Swift中迭代一个集合(而String是一个字符集合),那么使用reduce()
有时会更快。你可以使用reduce()
来实现你的大括号计数器:
let braces = javascriptFile.reduce(0, { count, char in
switch char {
case "{": return count + 1
case "}": return count - 1
default: return count
}
})
我不知道在你的情况下,这实际上是否比使用for
循环更快,但可能值得一试。如果没有别的,用这种方式写的意图非常明确。