Swift01/90Days - 空值合併運算符和區間運算符

空值合併運算符和區間運算符

今天主要看的內容是 Swift 中的基本運算符。記錄一下。html

Nil Coalescing Operator

a ?? b 中的 ?? 就是是空值合併運算符,會對 a 進行判斷,若是不爲 nil 則解包,不然就返回 bios

var a: String? = "a"
var b: String? = "b"
var c = a ?? b      // "a"
a = nil
c = a ?? b          // "b"
b = nil
c = a ?? b ?? "c"   // "c"

使用的時候有如下兩點要求:swift

  • a 必須是 optional 的
  • b 必須和 a 類型一致

也就是說,a 必定要有被備胎的可能,b 必定要有作備胎的資格。app

其實也就是對三目運算符的簡寫:oop

a != nil ? a! : b 或者 a == nil ? b : a!ui

固然你也能夠經過自定義運算符來實現:spa

infix operator ||| {}

func |||<T> (left: T?, right: T) -> T  {
    if let l = left { 
        return l 
    }
    return right
}

var a:String?
var b = "b"
var c = a ||| b

C# 中也有個 ?? ,感興趣的能夠去了解一下。code

Range Operator

區間運算符分爲閉區間 (...) 和左閉右開區間 (..<) 兩種,前者是算頭算尾,後者是算頭不算尾。htm

能夠應用在 switch 中:對象

switch aNumber
{
case 0...5:
    println("This number is between 0 and 5")
case 6...10:
    println("This number is between 6 and 10")
default:
    println("This number is not between 0 and 10")
}

區間運算符其實返回的是一個 Range<T> 對象,是一個連續無關聯序列索引的集合。

話說之前左閉右開是 .. ,這樣和 Ruby 的就恰好徹底相反了。。。

不過有人就是想用 .. ,那麼能夠這樣本身寫一個:

infix operator .. { associativity none precedence 135}

func .. (lhs: Int, rhs: Int) -> Range<Int> {
    return lhs..<rhs
}

for i in 0..10 {
    println("index \(i)")
}

你也能夠用 generate() 來遍歷:

var range = 1...4
var generator = range.generate()    // {startIndex 1, endIndex 5}
generator.next() // 1
generator.next() // 2
generator.next() // 3
generator.next() // 4
generator.next() // nil

.generate() 返回一個 RangeGenerator<T> 的結構體,能夠用來遍歷 Range<T> 中的值。

之前還有個 (5...1).by(-1) 的用法,不過如今好像沒用了。

區間運算符返回的是一個 ClosedInterval 或者 HalfOpenInterval 的東西,類型只要是 Comparable 就能夠了。因此咱們也能夠把 String 放到 ... 裏。

好比貓神的 Swifter Tips 中有一章的代碼以下,經過 String 的 ClosedInterval 來輸出字符串中的小寫字母:

let test = "Hello"
let interval = "a"..."z"

for c in test {
    if interval.contains(String(c)) {
        println("\(c)")
    }
}

SubString

Ruby 中用點點點來獲取 SubString 的方法很方便:

2.1.3 :001 > a="abc"
 => "abc"
2.1.3 :002 > a[0]
 => "a"
2.1.3 :003 > a[0..1]
 => "ab"

而 Swift 中的 ClosedInterval 是沒有 subscript 的。可是任性的咱們就是要用 [1...3] 這種方法怎麼辦呢?
本身動手豐衣足食,寫個 extension 吧,只須要加個 subscript 就能夠了,而後下標的類型是 Range<Int> 就能夠了:

extension String {
    subscript (r: Range<Int>) -> String {
        get {
            let startIndex = advance(self.startIndex, r.startIndex)
            let endIndex = advance(startIndex, r.endIndex - r.startIndex)

            return self[Range(start: startIndex, end: endIndex)]
        }
    }
}

var s = "Hello, playground"

println(s[0...5]) // ==> "Hello,"
println(s[0..<5]) // ==> "Hello"

若是要搜索目標字符串以後再截取 substring 能夠這樣:

let name = "Joris Kluivers"

let start = name.startIndex
let end = find(name, " ")

if (end != nil) {
    let firstName = name[start..<end!]
} else {
    // no space found
}

References

相關文章
相關標籤/搜索