Swift 中的字符串截取

Swift 中的字符串截取

發(fā)表于2016-12-14||100

Substring in Swift 3.0

Info:

macOS 10.12.2 Beta

Xcode 8.2 Beta

Swift 3.0

前言

最近更文的頻率也是越來(lái)越慢,除去已到期末的緣故,加上在忙老師的項(xiàng)目,自己的時(shí)間便被壓縮殆盡。不過(guò)好在Swift 設(shè)計(jì)模式基本上已經(jīng)更新完畢,下來(lái)就準(zhǔn)備補(bǔ)齊每個(gè)模式對(duì)應(yīng)的說(shuō)明。

在嘗試使用 Swift 實(shí)現(xiàn)《大話(huà)設(shè)計(jì)模式》一書(shū)中的解釋器模式時(shí),書(shū)中的 Demo 多次使用了截取字符串的方法,當(dāng)然,Swift 作為一門(mén)先進(jìn)的編程語(yǔ)言不會(huì)缺少這一常用的方法。然而在使用中,可能由于 Swift 是一門(mén)較為注重(類(lèi)型)安全的語(yǔ)言,其字符串截取方法使用方式與 Java 等編程語(yǔ)言便有一些語(yǔ)法上的不同。在 Swift 自身的迭代過(guò)程中,這部分的語(yǔ)法變化也很大。所以這次就來(lái)簡(jiǎn)單研究一下 Swift 中的字符串截取。需要注意的是,雖然 Swift 也可以使用 NSString 類(lèi)型的字符串,而且兩者可以很容易的橋接,但考慮到個(gè)人對(duì) Objective-C 的了解程度,便暫時(shí)不探討。

String.Index

Basics

索引與下標(biāo),即 index 和 subscript。一般來(lái)說(shuō),兩者的概念是類(lèi)似的,不過(guò)個(gè)人覺(jué)得索引有泛指的概念,而下標(biāo)是具體的。

Swift 中字符串的索引類(lèi)型并不是其他語(yǔ)言中的整型(int),而是 String.Index。String.Index,即標(biāo)注字符串的索引類(lèi)型。在 Swift 的標(biāo)準(zhǔn)庫(kù)中,可以看到其本質(zhì)是String.CharacterView.Index的別名。

/// The index type for subscripting a string.

publictypealiasIndex=String.CharacterView.Index

再進(jìn)一步查看String.CharacterView,即創(chuàng)建給定字符串的字符視圖類(lèi)型。

publicstructCharacterView{

/// Creates a view of the given string.

publicinit(_text:String)

}

常用的"maimieng.com".characters的類(lèi)型其實(shí)就是String.CharacterView類(lèi)型。.characters將字符串內(nèi)容轉(zhuǎn)化為字符序列的視圖。

start & end

字符串必然是一個(gè)字符的有限序列,Swift 為了方便開(kāi)發(fā)者迅速定位,便集成了startIndex和endIndex。但是需要注意的是:startIndex是指字符串的第一個(gè)字符的下標(biāo),而endIndex是指字符串的最后一個(gè)字符之后的下標(biāo)。當(dāng)字符串為空時(shí),startIndex和endIndex相同。

varstr ="maimieng.com"

print(str.characters.count)

print(str.startIndex)

print(str.endIndex)

// 12

// Index(_base: Swift.String.UnicodeScalarView.Index(_position: 0), _countUTF16: 1)

// Index(_base: Swift.String.UnicodeScalarView.Index(_position: 12), _countUTF16: 0)

從上面的 Demo 也可以看出,startIndex的位置為 0,而endIndex的位置為 12,等同于字符串的長(zhǎng)度,而不是字符串長(zhǎng)度減一。

除了給出了起始和結(jié)尾的下標(biāo),Swift 也提供了根據(jù)下標(biāo)定位其他索引的方法:

publicfuncindex(after i: String.Index)->String.Index

publicfuncindex(before i: String.Index)->String.Index

publicfuncindex(_i: String.Index, offsetBy n: String.IndexDistance)->String.Index

publicfuncindex(_i: String.Index, offsetBy n: String.IndexDistance, limitedBy limit: String.Index)->String.Index?

這樣就可以通過(guò)給出的startIndex和endIndex來(lái)定位到其他的下標(biāo)了。

varstr ="maimieng.com"

// 返回傳入下標(biāo)之后的下標(biāo)

print(str.index(after: str.startIndex))

// 返回傳入下標(biāo)之前的下標(biāo)

print(str.index(before: str.endIndex))

// 返回傳入下標(biāo)偏移后的下標(biāo)(偏移量可正可負(fù)可為 0)

print(str.index(str.startIndex, offsetBy:1))

// print(str.index(str.endIndex, offsetBy: 10))

// 作用同上,但如果超過(guò)傳入的界限返回 nil

print(str.index(str.endIndex, offsetBy:10, limitedBy: str.endIndex) ??"越界")

下標(biāo)之間的間距,也可以利用func distance(from start: String.Index, to end: String.Index) -> String.IndexDistance方法求出:

varstr ="maimieng.com"

print(str.distance(from: str.startIndex, to: str.endIndex))

// 12

print(str.distance(from: str.endIndex, to: str.startIndex))

// -12

Range

Range 即范圍,Swift 中實(shí)現(xiàn)了 Comparable 協(xié)議的類(lèi)型都可以用 Range 來(lái)表示范圍。以下的 Range 特指:Range。

Range 的構(gòu)造方法是init(uncheckedBounds bounds: (lower: Bound, upper: Bound))。即傳入一個(gè)元組,返回一個(gè)范圍。需要注意的是:這個(gè)范圍 Swift 是不會(huì)檢查的,需要程序員自覺(jué)維護(hù)。

varstr ="maimieng.com"

// 前閉后開(kāi)

letrangeA =Range(uncheckedBounds: (str.startIndex, str.endIndex))

print(rangeA)

// Index(_base: Swift.String.UnicodeScalarView.Index(_position: 0), _countUTF16: 1)..

print(str.substring(with: rangeA))

// maimieng.com

// 即使范圍首尾顛倒,也沒(méi)有報(bào)錯(cuò)

letrangeB =Range(uncheckedBounds: (str.endIndex, str.startIndex))

print(rangeB)

// Index(_base: Swift.String.UnicodeScalarView.Index(_position: 12), _countUTF16: 0)..

// 但在使用中會(huì)出錯(cuò)

// fatal error: Can't form Range with upperBound < lowerBound

// str.substring(with: rangeB)

在上面的 Demo 中,從輸出中也可以看出,init(uncheckedBounds bounds: (lower: Bound, upper: Bound))構(gòu)造的范圍是一個(gè)前閉后開(kāi)的區(qū)間。

Swift 中,字符串本身也能構(gòu)造出 Range,例如:得到字符串子串的范圍,若不存在則返回 nil:

varstr ="maimieng.com"

// 返回前閉后開(kāi)的范圍

print(str.range(of:".com") ??"不存在")

// Index(_base: Swift.String.UnicodeScalarView.Index(_position: 8), _countUTF16: 1)..

substring

在 Range 一節(jié)的 Demo 中,已經(jīng)使用了substring(with:)方法測(cè)試范圍的使用。Swift 中的字符串截取與其他語(yǔ)言其實(shí)是相似的,都是根據(jù)索引或索引范圍來(lái)截取,只是 Swift 中的索引的類(lèi)型不是整型,稍有麻煩。

varstr ="maimieng.com"

// 截取傳入范圍(左開(kāi)右閉)的子串

letrange =Range(uncheckedBounds: (str.startIndex, str.endIndex))

print(str.substring(with: range))

// 從傳入的索引開(kāi)始截取到末尾(含 str.startIndex 元素)

print(str.substring(from: str.startIndex))

// 從傳入的索引的前一個(gè)位置開(kāi)始截取到頭部(不含 str.endIndex 元素)

print(str.substring(to: str.endIndex))

// maimieng.com

// maimieng.com

// maimieng.com

以上的 Demo 便是 Swift 中最基本的截取字符串使用。然而有時(shí)候條件一多,代碼的重復(fù)率也會(huì)增加,那么可以利用 Swift 中的

extension 來(lái)擴(kuò)展原有的 String,讓 Swift 的 String 可以像 C#、Java 一樣截取字符串,需要注意的是 這里的

IndexDistance 實(shí)際上是 String.CharacterView.IndexDistance 的別名,而

String.CharacterView.IndexDistance 又是 Int 類(lèi)型的別名。

extensionString{

funcsubstring(from: IndexDistance)->String? {

letindex =self.index(self.startIndex, offsetBy: from)

returnstr.substring(from: index)

}

funcsubstring(to: IndexDistance)->String? {

letindex =self.index(self.startIndex, offsetBy: to +1)

returnstr.substring(to: index)

}

funcsubstring(with range: Range)->String? {

letlower =self.index(self.startIndex, offsetBy: range.lowerBound)

letupper =self.index(self.startIndex, offsetBy: range.upperBound)

letrange =Range(uncheckedBounds: (lower, upper))

returnstr.substring(with: range)

}

funcsubstring(_lower: IndexDistance,_range: IndexDistance)->String? {

letlowerIndex =self.index(self.startIndex, offsetBy: lower)

letupperIndex =self.index(lowerIndex, offsetBy: range)

letrange =Range(uncheckedBounds: (lowerIndex, upperIndex))

returnstr.substring(with: range)

}

}

print(str.substring(to:0) ??"nil")

print(str.substring(from:2) ??"nil")

print(str.substring(with:0..<1) ??"nil")

print(str.substring(1,2) ??"nil")

// m

// imieng.com

// m

// ai

參考資料

Documentation & API Reference

原文出處:https://maimieng.com/2016/37/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評(píng)論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,980評(píng)論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 64,064評(píng)論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評(píng)論 6 414
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 56,109評(píng)論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,287評(píng)論 0 291
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評(píng)論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評(píng)論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,327評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,667評(píng)論 1 296
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容

  • 由于種種原因,簡(jiǎn)書(shū)等第三方平臺(tái)博客不再保證能夠同步更新,歡迎移步 GitHub:https://github.co...
    萌面大道閱讀 5,471評(píng)論 2 4
  • 1 .字符串字面量 String 在Swift中字符串字面量是由雙引號(hào)" " 包裹著的 像我們?cè)?Swift 3 ...
    iceMaple閱讀 1,140評(píng)論 1 2
  • 突然發(fā)現(xiàn),人不能閑著。因?yàn)橐挥锌臻e時(shí)間,腦子就不思考了。然后就會(huì)回憶過(guò)去,感傷現(xiàn)在,繼而胡思亂想。 畢業(yè)兩個(gè)多月的...
    Diana心情日記閱讀 193評(píng)論 0 0
  • 又和一個(gè)朋友討論了相親結(jié)婚的事,又是一個(gè)嘲諷我的理想主義的朋友...可能我對(duì)于婚姻的看法還是停留在等于愛(ài)情的階段 ...
    heim_dn閱讀 218評(píng)論 0 0