【问题标题】:How to convert "Index" to type "Int" in Swift?如何在 Swift 中将“Index”转换为“Int”类型?
【发布时间】:2016-04-05 01:22:31
【问题描述】:

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

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)

感谢任何帮助。

【问题讨论】:

  • 你有 xcode 7.2 和 swift 2.x 吗?
  • 没有什么比在操场上看到你想要盯着你的脸的索引更令人沮丧的了,它是一个巨大的 PITA 将索引转换为你需要的那种。
  • Swift 3:let index = letters.characters.index(of: "c") 下一行 let int_index = letters.characters.distance(from: letters.startIndex, to: index)
  • 苹果WTF!!!!!!
  • 已经阅读了几个小时。仍然不知道发生了什么。这是一个奇怪的世界吗?

标签: string swift


【解决方案1】:

编辑/更新:

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")
}

【讨论】:

  • 我很困惑为什么他们不决定创建一个返回数组元素的整数值索引的函数.. smh
  • 并非所有字符都可以存储在一个字节中。你应该花点时间阅读 Swift String 文档
  • Tbh 我正在尝试获取常规数组元素的整数值索引,而不是字符串。
  • 让简单的事情变得不必要的复杂:(
【解决方案2】:

适用于 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) -&gt; String.IndexDistance 返回一个IndexDistance,它只是Inttypealias

【讨论】:

  • 谢谢!最佳答案!请用“myString”替换“number”
  • 已修复!转换时忘记更改。
  • 你将如何使用lastIndex(of: "") 来执行此操作,它也只会返回那个奇怪的String.Index
  • @Neph 除了你在第 3 行使用 lastIndex(of: ) 代替 firstIndex(of: ) 之外,这实际上是完全相同的东西
  • @Neph 它所做的只是获取字母的第一个索引(或最后一个索引)并将其存储在常量i 中。然后它计算从字符串的起始索引到i 的距离。这些都是我使用的 Swift 提供的内置方法。
【解决方案3】:

斯威夫特 4

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

注意:如果 String 包含相同的多个字符,它会从左边获取最近的一个

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

【讨论】:

  • 不要使用encodedOffset。 encodedOffset 已弃用:encodedOffset 已弃用,因为最常见的用法不正确。 试试"??????".index(of: "??")?.encodedOffset // 16
  • @LeoDabus 您正确地声明它已被弃用。但无论如何,您都建议将其用作答案。正确答案是:index_Of_YourStringVariable.utf16Offset(in: yourStringVariable)
  • 没有。 UTF16 偏移它可能不是你想要的
【解决方案4】:

encodedOffset 已从 Swift 4.2 中弃用。

弃用消息: encodedOffset 已被弃用,因为最常见的用法不正确。使用utf16Offset(in:) 实现相同的行为。

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

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

【讨论】:

  • 尝试let str = "??????" let index = str.firstIndex(of: "??")?.utf16Offset(in: str) // 结果:8
【解决方案5】:

搜索这样的索引时

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

它被视为 Array.Index。你必须给编译器一个你想要一个整数的线索

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

【讨论】:

    【解决方案6】:

    要根据索引进行字符串操作,传统的索引数值方法是做不到的。因为 swift.index 是由 indices 函数检索的,而不是 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

    提前致谢

    【讨论】:

    • 这可以通过过滤器轻松完成var counter = 0let result = mystr.filter { _ indefer { counter += 1 }return counter.isMultiple(of: 2)}
    • 如果您更喜欢使用 String.index var index = mystr.startIndex let result = mystr.filter { _ in defer { mystr.formIndex(after: &amp;index) } return mystr.distance(from: mystr.startIndex, to: index).isMultiple(of: 2) }
    【解决方案7】:

    Here is an extension 可以让您以Ints 的形式访问子字符串的边界,而不是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 选择让它变得困难的原因。 (虽然这是一个值得商榷的设计决定——通过让它变得困难来隐藏一个危险的东西......)

    您可以在String documentation from Apple 中阅读更多信息,但要注意的是,它源于这些“索引”实际上是特定于实现的事实。它们表示在操作系统呈现字符串之后 中的索引,因此可以根据使用的 Unicode 规范的版本从操作系统切换到操作系统。这意味着按索引访问值不再是一个恒定时间的操作,因为必须在数据上运行 UTF 规范才能确定字符串中的正确位置。如果您桥接到它,这些索引也不会与 NSString 生成的值对齐,或者与底层 UTF 标量的索引对齐。警告开发者。

    【讨论】:

    • 不需要再从 startIndex 测量距离。只需获取从下到上的距离并添加起点即可。
    • 我还会将选项添加到您的方法中。类似func rangeInt&lt;S: StringProtocol&gt;(of aString: S, options: String.CompareOptions = []) -&gt; Range&lt;Int&gt;? {guard let range = range(of: aString, options: options) else { return nil }let start = distance(from: startIndex, to: range.lowerBound)return start..&lt;start+distance(from: range.lowerBound, to: range.upperBound)}
    • 我可能会将方法名称更改为countableRange 并返回CountableRange
    • 全面的好建议@LeoDabus。实际上,我添加了所有 range(of...) 参数,因此您现在可以调用 countableRange(of:, options:, range:,locale:)。已经更新了要点,也会更新这篇文章。
    • 考虑到您可以在子字符串上调用该方法,我不需要范围
    【解决方案8】:

    如果您遇到“索引超出范围”错误。你可以试试这个方法。在 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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-11-17
      • 1970-01-01
      • 2016-03-12
      • 1970-01-01
      • 1970-01-01
      • 2015-08-20
      • 1970-01-01
      • 1970-01-01
      • 2016-07-01
      相关资源
      最近更新 更多