在Swift编程语言中获取字符串的第n个字符

本文翻译自:Get nth character of a string in Swift programming language

How can I get the nth character of a string? 如何获得字符串的第n个字符? I tried bracket( [] ) accessor with no luck. 我试过没有运气的方括号( [] )访问器。

var string = "Hello, world!"

var firstChar = string[0] // Throws error

ERROR: 'subscript' is unavailable: cannot subscript String with an Int, see the documentation comment for discussion 错误:“下标”不可用:无法对带Int的字符串进行下标,请参见文档注释以进行讨论


#1楼

参考:https://stackoom.com/question/1d5eu/在Swift编程语言中获取字符串的第n个字符


#2楼

The swift string class does not provide the ability to get a character at a specific index because of its native support for UTF characters. swift字符串类不提供在特定索引处获取字符的功能,因为其对UTF字符的本机支持。 The variable length of a UTF character in memory makes jumping directly to a character impossible. UTF字符在内存中的可变长度使得无法直接跳转到字符。 That means you have to manually loop over the string each time. 这意味着您每次都必须手动遍历字符串。

You can extend String to provide a method that will loop through the characters until your desired index 您可以扩展String以提供一种方法,该方法将循环遍历字符,直到所需的索引为止

extension String {
    func characterAtIndex(index: Int) -> Character? {
        var cur = 0
        for char in self {
            if cur == index {
                return char
            }
            cur++
        }
        return nil
    }
}

myString.characterAtIndex(0)!

#3楼

Swift's String type does not provide a characterAtIndex method because there are several ways a Unicode string could be encoded. Swift的String类型不提供characterAtIndex方法,因为可以通过多种方式对Unicode字符串进行编码。 Are you going with UTF8, UTF16, or something else? 您要使用UTF8,UTF16还是其他?

You can access the CodeUnit collections by retrieving the String.utf8 and String.utf16 properties. 您可以通过检索String.utf8String.utf16属性来访问CodeUnit集合。 You can also access the UnicodeScalar collection by retrieving the String.unicodeScalars property. 您还可以通过检索String.unicodeScalars属性来访问UnicodeScalar集合。

In the spirit of NSString 's implementation, I'm returning a unichar type. 本着NSString实现的精神,我返回了一个unichar类型。

extension String
{
    func characterAtIndex(index:Int) -> unichar
    {
        return self.utf16[index]
    }

    // Allows us to use String[index] notation
    subscript(index:Int) -> unichar
    {
        return characterAtIndex(index)
    }
}

let text = "Hello Swift!"
let firstChar = text[0]

#4楼

Attention: Please see Leo Dabus' answer for a proper implementation for Swift 4. 注意:请参阅Leo Dabus的答案以获取对Swift 4的正确实现。

Swift 4 斯威夫特4

The Substring type was introduced in Swift 4 to make substrings faster and more efficient by sharing storage with the original string, so that's what the subscript functions should return. 在Swift 4中引入了Substring类型,以通过与原始字符串共享存储来使子字符串更快,更有效,这就是下标函数应该返回的内容。

Try it out here 在这里尝试

extension String {
  subscript (i: Int) -> Character {
    return self[index(startIndex, offsetBy: i)]
  }
  subscript (bounds: CountableRange<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[start ..< end]
  }
  subscript (bounds: CountableClosedRange<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[start ... end]
  }
  subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(endIndex, offsetBy: -1)
    return self[start ... end]
  }
  subscript (bounds: PartialRangeThrough<Int>) -> Substring {
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[startIndex ... end]
  }
  subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[startIndex ..< end]
  }
}
extension Substring {
  subscript (i: Int) -> Character {
    return self[index(startIndex, offsetBy: i)]
  }
  subscript (bounds: CountableRange<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[start ..< end]
  }
  subscript (bounds: CountableClosedRange<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[start ... end]
  }
  subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(endIndex, offsetBy: -1)
    return self[start ... end]
  }
  subscript (bounds: PartialRangeThrough<Int>) -> Substring {
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[startIndex ... end]
  }
  subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[startIndex ..< end]
  }
}

To convert the Substring into a String , you can simply do String(string[0..2]) , but you should only do that if you plan to keep the substring around. 要将Substring转换为String ,您可以简单地执行String(string[0..2]) ,但是只有在计划保留子字符串的情况下才应该这样做。 Otherwise, it's more efficient to keep it a Substring . 否则,将其保留为Substring更为有效。

It would be great if someone could figure out a good way to merge these two extensions into one. 如果有人能找到一种很好的方法将这两个扩展合并为一个,那将是很好的。 I tried extending StringProtocol without success, because the index method does not exist there. 我尝试扩展StringProtocol失败,因为那里没有index方法。

Swift 3: 斯威夫特3:

extension String {
  subscript (i: Int) -> Character {
    return self[index(startIndex, offsetBy: i)]
  }
  subscript (i: Int) -> String {
    return String(self[i] as Character)
  }
  subscript (r: Range<Int>) -> String {
    let start = index(startIndex, offsetBy: r.lowerBound)
    let end = index(startIndex, offsetBy: r.upperBound)
    return self[Range(start ..< end)]
  }
}

Why is this not built-in? 为什么这不是内置的?

Apple provides the following explanation ( found here ): 苹果提供了以下说明(可在此处找到 ):

Subscripting strings with integers is not available. 用整数下标字符串不可用。

The concept of "the i th character in a string" has different interpretations in different libraries and system components. “字符串中的第i个字符”的概念在不同的库和系统组件中具有不同的解释。 The correct interpretation should be selected according to the use case and the APIs involved, so String cannot be subscripted with an integer. 应该根据用例和所涉及的API选择正确的解释,因此String不能用整数下标。

Swift provides several different ways to access the character data stored inside strings. Swift提供了几种不同的方式来访问存储在字符串中的字符数据。

  • String.utf8 is a collection of UTF-8 code units in the string. String.utf8是字符串中UTF-8代码单元的集合。 Use this API when converting the string to UTF-8. 将字符串转换为UTF-8时,请使用此API。 Most POSIX APIs process strings in terms of UTF-8 code units. 大多数POSIX API按照UTF-8代码单位处理字符串。

  • String.utf16 is a collection of UTF-16 code units in string. String.utf16是字符串中UTF-16代码单元的集合。 Most Cocoa and Cocoa touch APIs process strings in terms of UTF-16 code units. 大多数Cocoa和Cocoa touch API按照UTF-16代码单位处理字符串。 For example, instances of NSRange used with NSAttributedString and NSRegularExpression store substring offsets and lengths in terms of UTF-16 code units. 例如,与NSAttributedStringNSRegularExpression NSRange使用的NSAttributedString实例以UTF-16代码单位存储子字符串偏移量和长度。

  • String.unicodeScalars is a collection of Unicode scalars. String.unicodeScalars是Unicode标量的集合。 Use this API when you are performing low-level manipulation of character data. 在执行字符数据的低级操作时,请使用此API。

  • String.characters is a collection of extended grapheme clusters, which are an approximation of user-perceived characters. String.characters是扩展的字素簇的集合,这些簇是用户感知的字符的近似值。

Note that when processing strings that contain human-readable text, character-by-character processing should be avoided to the largest extent possible. 请注意,在处理包含人类可读文本的字符串时,应尽可能避免逐字符处理。 Use high-level locale-sensitive Unicode algorithms instead, for example, String.localizedStandardCompare() , String.localizedLowercaseString , String.localizedStandardRangeOfString() etc. 请改用高级区域设置敏感的Unicode算法,例如String.localizedStandardCompare()String.localizedLowercaseStringString.localizedStandardRangeOfString()等。


#5楼

我只是想出了这个巧妙的解决方法

var firstChar = Array(string)[0]

#6楼

No indexing using integers, only using String.Index . 不使用整数索引,仅使用String.Index Mostly with linear complexity. 通常具有线性复杂度。 You can also create ranges from String.Index and get substrings using them. 您还可以从String.Index创建范围并使用它们获取子字符串。

Swift 3.0 斯威夫特3.0

let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.index(before: someString.endIndex)]
let charAtIndex = someString[someString.index(someString.startIndex, offsetBy: 10)]

let range = someString.startIndex..<someString.index(someString.startIndex, offsetBy: 10)
let substring = someString[range]

Swift 2.x 斯威夫特2.x

let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.endIndex.predecessor()]
let charAtIndex = someString[someString.startIndex.advanceBy(10)]

let range = someString.startIndex..<someString.startIndex.advanceBy(10)
let subtring = someString[range]

Note that you can't ever use an index (or range) created from one string to another string 请注意,您永远无法使用从一个字符串创建到另一个字符串的索引(或范围)

let index10 = someString.startIndex.advanceBy(10)

//will compile
//sometimes it will work but sometimes it will crash or result in undefined behaviour
let charFromAnotherString = anotherString[index10]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值