あなただけの最初の文字を大文字する必要がある場合は、以下のuppercase2()
を使用してください。それは文字列全体を大文字にするよりも5倍のスピードアップです。千万目で
import Foundation
// too slow, maybe with some bitwise operations could get faster ♀️
func uppercase(_ string: String) -> Character? {
let key: Int8 = string.utf8CString[0]
guard key>0, key<127, let c = Unicode.Scalar(Int(key >= 97 ? key - Int8(32) : key)) else { return nil }
return Character(c)
}
// winner but using internal _core stuff
func uppercase2(_ string: String) -> Character? {
guard let key = string._core.asciiBuffer?[0] else { return nil }
return Character(Unicode.Scalar(key >= 97 ? key - 32 : key)) // use < + to lowercase
}
func measure(times: Int, task:()->()){
let start1 = CFAbsoluteTimeGetCurrent()
for _ in 1..<times {
task()
}
print(CFAbsoluteTimeGetCurrent() - start1)
}
print("".uppercased().first as Any) // Optional("")
print(uppercase("") as Any) // nil
print(uppercase2("") as Any) // nil
measure(times: 10_000_000) { _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".uppercased().first } // 4.17883902788162
measure(times: 10_000_000) { _ = uppercase("ABCDEFGHIJKLMNOPQRSTUVWXYZ") } // 4.91275697946548
measure(times: 10_000_000) { _ = uppercase2("ABCDEFGHIJKLMNOPQRSTUVWXYZ") } // 0.720575034618378
、Appleのuppercased
でも力アンラップで、より速くこの記事の下部にあるコードよりも148x回走りました。私はコメディー目的のためにそれを残すでしょう。
彼らのアプローチはもちろん、低レベルです。 lowercased()を参照してください。彼らは、内部asciiBufferを確認し、_asciiUpperCaseTableを使用します。
元のStringがすでにSwift Stringの場合は、ASCIIレベルの文字を扱うように既に最適化されたStringCoreクラスで表されます。したがって、Swiftの大文字の機能を破ることはできません。
答えの種類:最も速い方法は、通常のuppercase()
関数を使用することです。
「私のユースケースは言語目的ではない」とは、私がASCIIのみを使用していることを意味します。これが提供する利点は、UTF-8とASCIIが同じスカラーコードを共有しているため、上/下ケーシングは固定数を減算または追加することを意味します。
import Foundation
print("a".unicodeScalars.first!.value) // 97
print("A".unicodeScalars.first!.value) // 65
let uppercase = String("abcde".flatMap {
guard let char = $0.unicodeScalars.first,
let uppercased = Unicode.Scalar(char.value - UInt32(97 - 65))
else {
return nil
}
return Character(uppercased)
})
print(uppercase) // ABCDE
おかげさまで、詳細な答えをいただきありがとうございました。第2に、私はStringクラスのソースコードを見ることができます。私の場合、私はASCII文字列の最初の文字を取得しており、それを下位または大文字のいずれかに強制して辞書のキーとして使用します。私は文字列全体に対してlowercased()を実行し、最初の文字を取得できますが、コードのサブセットを使用する方が良いでしょうか? –
文字列全体を大文字にするよりも6倍速の場合は、大文字2を参照してください。それでも、コードを改善する方法はたくさんありますが、現時点でどうなっているのか分かりません。 – Jano