如何在 Swift 中将“ Index”转换为“ Int”?

我希望将字符串中包含的字母的索引转换为整数值。尝试读取头文件,但是我找不到 Index的类型,尽管它似乎符合使用方法(例如 distanceTo)的协议 ForwardIndexType

var letters = "abcdefg"
let index = letters.characters.indexOf("c")!


// ERROR: Cannot invoke initializer for type 'Int' with an argument list of type '(String.CharacterView.Index)'
let intValue = Int(index)  // I want the integer value of the index (e.g. 2)

感谢你的帮助。

92721 次浏览

编辑/更新:

Xcode 11• Swift 5.1或更高版本

extension StringProtocol {
func distance(of element: Element) -> Int? { firstIndex(of: element)?.distance(in: self) }
func distance<S: StringProtocol>(of string: S) -> Int? { range(of: string)?.lowerBound.distance(in: self) }
}

extension Collection {
func distance(to index: Index) -> Int { distance(from: startIndex, to: index) }
}

extension String.Index {
func distance<S: StringProtocol>(in string: S) -> Int { string.distance(to: self) }
}

操场测试

let letters = "abcdefg"


let char: Character = "c"
if let distance = letters.distance(of: char) {
print("character \(char) was found at position #\(distance)")   // "character c was found at position #2\n"
} else {
print("character \(char) was not found")
}

let string = "cde"
if let distance = letters.distance(of: string) {
print("string \(string) was found at position #\(distance)")   // "string cde was found at position #2\n"
} else {
print("string \(string) was not found")
}

Swift 4

var str = "abcdefg"
let index = str.index(of: "c")?.encodedOffset // Result: 2

注意: 如果 绳子包含相同的多个字符,那么它将从左起得到最接近的一个

var str = "abcdefgc"
let index = str.index(of: "c")?.encodedOffset // Result: 2

要根据索引执行字符串操作,无法使用传统的索引数值方法。因为 ift. index 是由 index 函数检索的,而且不属于 Int 类型。尽管 String 是一个字符数组,但我们仍然不能按索引读取元素。

真是令人沮丧。

因此,要创建字符串的每个偶数字符的新子字符串,请检查下面的代码。

let mystr = "abcdefghijklmnopqrstuvwxyz"
let mystrArray = Array(mystr)
let strLength = mystrArray.count
var resultStrArray : [Character] = []
var i = 0
while i < strLength {
if i % 2 == 0 {
resultStrArray.append(mystrArray[i])
}
i += 1
}
let resultString = String(resultStrArray)
print(resultString)

输出: acegikmoqsuwy

提前谢谢

encodedOffset已从 Swift 4.2弃用。

弃权信息: 由于最常见的用法是不正确的,所以不推荐使用 encodedOffset。使用 utf16Offset(in:)可以实现相同的行为。

所以我们可以这样使用 utf16Offset(in:):

var str = "abcdefgc"
let index = str.index(of: "c")?.utf16Offset(in: str) // Result: 2

这里有一个扩展 ,它允许您以 Int而不是 String.Index值的形式访问子字符串的边界:

import Foundation


/// This extension is available at
/// https://gist.github.com/zackdotcomputer/9d83f4d48af7127cd0bea427b4d6d61b
extension StringProtocol {
/// Access the range of the search string as integer indices
/// in the rendered string.
/// - NOTE: This is "unsafe" because it may not return what you expect if
///     your string contains single symbols formed from multiple scalars.
/// - Returns: A `CountableRange<Int>` that will align with the Swift String.Index
///     from the result of the standard function range(of:).
func countableRange<SearchType: StringProtocol>(
of search: SearchType,
options: String.CompareOptions = [],
range: Range<String.Index>? = nil,
locale: Locale? = nil
) -> CountableRange<Int>? {
guard let trueRange = self.range(of: search, options: options, range: range, locale: locale) else {
return nil
}


let intStart = self.distance(from: startIndex, to: trueRange.lowerBound)
let intEnd = self.distance(from: trueRange.lowerBound, to: trueRange.upperBound) + intStart


return Range(uncheckedBounds: (lower: intStart, upper: intEnd))
}
}

要知道,这可能会导致奇怪的结果,这就是为什么苹果选择让它变得更难。(尽管这是一个有争议的设计决定——仅仅通过使其难以实现来隐藏一个危险的东西... ...)

您可以在 来自 Apple 的字符串文档中阅读更多内容,但 tldr 源于这样一个事实,即这些“索引”实际上是特定于实现的。它们表示字符串 在由操作系统呈现之后中的索引,因此可以根据所使用的 Unicode 规范的版本从操作系统转换为操作系统。这意味着通过 index 访问值不再是一个常量时间操作,因为必须在数据上运行 UTF 规范来确定字符串中的正确位置。如果与 NSString 连接,这些索引也不会与 NSString 生成的值一致,或者与底层 UTF 标量的索引一致。注意显影剂。

当搜索这样的索引时

⛔️ guard let index = (positions.firstIndex { position <= $0 }) else {

你必须给编译器一个你想要一个整数的线索

✅ guard let index: Int = (positions.firstIndex { position <= $0 }) else {

Xcode 13Swift 5工作

let myString = "Hello World"


if let i = myString.firstIndex(of: "o") {
let index: Int = myString.distance(from: myString.startIndex, to: i)
print(index) // Prints 4
}

函数 func distance(from start: String.Index, to end: String.Index) -> String.IndexDistance返回一个 IndexDistance,它只是 Inttypealias

如果你得到一个“索引超出界限”错误。你可以尝试这种方法。在 Swift 5中工作

extension String{


func countIndex(_ char:Character) -> Int{
var count = 0
var temp = self
  

for c in self{
            

if c == char {
               

//temp.remove(at: temp.index(temp.startIndex,offsetBy:count))
//temp.insert(".", at: temp.index(temp.startIndex,offsetBy: count))
                

return count


}
count += 1
}
return -1
}
}

Swift 5

您可以转换为字符数组,然后使用 advanced(by:)转换为整数。

let myString = "Hello World"


if let i = Array(myString).firstIndex(of: "o") {
let index: Int = i.advanced(by: 0)
print(index) // Prints 4
}