LoginSignup
4
1

More than 1 year has passed since last update.

【Swift】文字列のinsertをExtensionで便利にしてみる

Last updated at Posted at 2023-03-24

●Swiftのinsertはなぜこんなにめんどいのか

Swiftで文字列の任意の位置にinsertしたい時って、こんな感じに結構めんどい。
先頭からとか末尾からとか考えるのも結構めんどい。

var str = "HelloWorld"
 
// 先頭から1文字目と2文字目の間に文字列を挿入
str.insert("★", at: str.index(str.startIndex, offsetBy: 1)) // H★elloWorld
 
// 末尾から5文字目と6文字目の間に文字列を挿入
str.insert("★", at: str.index(str.endIndex, offsetBy: -5)) // Hello★World

しかもターゲットの文字列の範囲外のindexを指定した場合は、クラッシュする。

var str = "HelloWorld"
 
// 先頭から1文字目と2文字目の間に文字列を挿入
str.insert("★", at: str.index(str.startIndex, offsetBy: 11))
     // → error: Execution was interrupted, reason: EXC_BREAKPOINT

●メンドいことは Extension で解決しよう

下記のようにString型のExtensionを作ってみると結構便利になる。

import Foundation

extension String {
    enum InsertFrom {
        case front
        case back
    }
    
    func insert(_ str: String, at index: Int, from direction: InsertFrom) -> String {
        if self.count < index { return self }
        
        let firstIndex = direction == .front ? index : self.count - index
        let secondIndex = direction == .front ? self.count - index : index
        
        return prefixString(firstIndex) + str + suffixString(secondIndex)
    }
}

extension String {
    func prefixString(_ index: Int) -> String {
        return String(self.prefix(index))
    }
    
    func suffixString(_ index: Int) -> String {
        return String(self.suffix(index))
    }
}

●Point

at index: Int
  → 挿入したい位置をindex指定する

from direction: InsertFrom
  → indexを先頭or末尾、どちらから指定するかenumInsertFromを指定する

if self.count < index { return self }
  → 範囲外のindexを指定した場合は文字列をそのままreturnし、クラッシュ回避

prefixString suffixString
  →prefix suffixの返り値がSubstringでダルいので
   これもStringを返すようにExtensionしちゃう

●使うとこんな感じ

var str = "HelloWorld"
 
// 先頭から1文字目と2文字目の間に文字列を挿入
let result1 = str.insert("★", at: 1, from: .front) // H★elloWorld
 
// 末尾から5文字目と6文字目の間に文字列を挿入
let result2 = str.insert("★", at: 5, from: .back) // Hello★World

クラッシュもしない

var str = "HelloWorld"
 
// 範囲外のindexに文字列を挿入
let result = str.insert("★", at: 11, from: .front) // HelloWorld

外部引数のおかげで より英文的 に呼び出せるのも結構気に入ってる。
Insert string at third from front. みたいにね。

他にも何かExtension思いついたら投稿しようと思います✌️

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1