Skip to content

Instantly share code, notes, and snippets.

@KentarouKanno
Last active April 30, 2018 14:36
Show Gist options
  • Save KentarouKanno/0bea0532c53b7a1c271e6671f4a297a8 to your computer and use it in GitHub Desktop.
Save KentarouKanno/0bea0532c53b7a1c271e6671f4a297a8 to your computer and use it in GitHub Desktop.

参考URL: http://gootara.org/library/2017/09/swift4substr.html
https://qiita.com/risuke/items/cdd6a75f236faae3ce6b

let text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

print(text[..<text.index(text.startIndex, offsetBy: 6)])
// => "ABCDEF" 先頭から指定インデックスまで No.1

print(text.prefix(6))
// => "ABCDEF" 先頭から指定インデックスまで No.2

print(text[text.index(text.startIndex, offsetBy: 20)...])
// => "UVWXYZ" 指定インデックスから終端まで No.1

print(text[text.index(text.endIndex, offsetBy: -6)...])
// => "UVWXYZ" 指定インデックスから終端まで、No.2

print(text.suffix(6))
// => "UVWXYZ" 末尾からx文字

print(text.prefix(text.count - 1))
// => "ABCDEFGHIJKLMNOPQRSTUVWXY" 末尾1文字を削除

print(text[text.index(text.startIndex, offsetBy: 10)..<text.index(text.endIndex, offsetBy: -10)])
// => "KLMNOP"  開始~終了指定

print(text[text.index(text.startIndex, offsetBy: 10)...text.index(text.endIndex, offsetBy: -10)])
// => "KLMNOPQ"

// 以下のように切り出すことも可能です
if let startIndex = text.index(of: "K"), let endIndex = text.index(of: "P") {
    print(text[startIndex...endIndex])
    // => "KLMNOP"
}

// start - end ではなく長さで指定したい場合のサンプル
let startIndex = text.index(text.startIndex, offsetBy: 2) // 開始位置 2
let endIndex = text.index(startIndex, offsetBy: 6) // 長さ 6
print(text[startIndex..<endIndex])
// => "CDEFGH"

// 以下のように不正なインデックスを指定すると、アプリが落ちてしまうので気をつけましょう
//print(text[text.index(text.startIndex, offsetBy: 32)...])
// 必要に応じて limitedBy を指定すれば、index が不正な場合は nil が返されます
if let index = text.index(text.startIndex, offsetBy: 32, limitedBy: text.endIndex) {
    print(text[index...])
}

// 部分的に取り出した結果は文字列(String)ではなく部分文字列(Substring)です
// 文字列とほぼ同様に扱えますが、必要に応じて String に変換しましょう
let substr = text[..<text.index(text.startIndex, offsetBy: 6)]
print("substr = \(substr) / \(type(of:substr))")
// => "substr = ABCDEF / Substring"
let str = String(substr)
print("str = \(str) / \(type(of:str))")
// => "str = ABCDEF / String"


// 移行  swift3 → swift4
if let match:Range<String.Index> = text.range(of: "[^/]*$", options: .regularExpression) {
    // text.substring(with: match) ↓ swift3 → swift4
    text = String(text[match.lowerBound ..< match.upperBound])
}

★ Extension

// Extensionを使用
print(text.substring(1...5))
// => "BCDEF"
print(text.substring(1..<5))
// => "BCDE"
print(text.substring(1...))
// => "BCDEFGHIJKLMNOPQRSTUVWXYZ"
print(text.substring(...5))
// => "ABCDE"

extension String {
    
    func substring(_ r: CountableRange<Int>) -> String {
        
        let length = self.count
        let fromIndex = (r.startIndex > 0) ? self.index(self.startIndex, offsetBy: r.startIndex) : self.startIndex
        let toIndex = (length > r.endIndex) ? self.index(self.startIndex, offsetBy: r.endIndex) : self.endIndex
        
        if fromIndex >= self.startIndex && toIndex <= self.endIndex {
            return String(self[fromIndex ..< toIndex])
        }
        
        return String(self)
    }
    
    func substring(_ r: CountableClosedRange<Int>) -> String {
        
        let from = r.lowerBound
        let to = r.upperBound
        
        return self.substring(from ..< (to + 1))
    }
    
    func substring(_ r: CountablePartialRangeFrom<Int>) -> String {
        
        let from = r.lowerBound
        let to = self.count
        
        return self.substring(from ..< to)
    }
    
    func substring(_ r: PartialRangeThrough<Int>) -> String {
        
        let from = 0
        let to = r.upperBound
        
        return self.substring(from ..< to)
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment