LoginSignup
3
2

More than 5 years have passed since last update.

swift3 で (文字列)固定長分割

Posted at

はじめに

以前swift2で実装していたものをswift3.0に移植するにあたり、ちょっとハマった、修正履歴として残しておこうと思う。

以前の記事はこちら>swift2 で 固定長分割

前置き

なぜこんな実装が必要なのというのに対して、特に回答する予定はありません、諸般の事情でとだけ:smirk:

参考にしたページ

結局エラーメッセージが一番参考になるのですが、そのメッセージをもとに、どのように直すかという部分で参考にしています。
- swift migration guid
- apple-api-reference: stride function
- apple-api-reference: string function
- blog: ranges
- blog: strings

変わった部分

短いコードの割に変わった部分が結構ありました。
- stride
- advancedBy
- joinWithSeparator

stride

これは、stride(to:flag_by:)が無くなっていて、stride(from:flag_to:by:)に置き換える必要がありました。
swift:String+Splitter.swift
0.stride(to: limit, by: len).forEach {

これが、以下のようになりました。
swift:String+Splitter.swift
stride(from: 0, to: limit, by: len).forEach {

advancedBy

indexで頑張ります

joinWithSeparator

joined(separator:)に変わりました。

とりあえず、コードを載せます

String+Spritter.swift


extension String {

  /** 文字列を固定長で分割する
  - Parameter len: 分割する長さ
  - Parameter handle: 分割ごとに呼び出される
  */
  public func Splitter(_ len: Int, handle: ((_ cut: String, _ isLast: Bool)->())) {
  {
    let limit = self.characters.count
    stride(from: 0, to: limit, by: len).forEach {
      p in
      guard let st = self.index(startIndex,offsetBy:p, limitedBy: endIndex)
         else {
            handle("",true)
            return
         }
      guard let end = self.index(st, offsetBy: len, limitedBy: endIndex)
         else {
            let cut = self.substring(from: st)
            handle(cut,true)
            return
         }
      let cut = self.substring(with: st..<end)
      handle(cut, end == endIndex)
    }
  }

}

書き直し

以前のコードより実行時間が遅くなってしまいました、以前のコードにできるだけ似せてみます。

String+Spritter.swift
  /** 文字列を固定長で分割する
  - Parameter len: 分割する長さ
  - Parameter handle: 分割ごとに呼び出される
  */
    public func Splitter(len: Int, handle: ((_ cut: String, _ isLast: Bool)->())) {
        let array = self.characters.map { String($0) }
        let limit = self.characters.count
        stride(from: 0, to: limit, by: len).forEach {
            p in
            guard let st = array.index(array.startIndex,offsetBy:p, limitedBy: array.endIndex)
                else {
                    handle("",true)
                    return
                }
            guard let end = array.index(st, offsetBy: len, limitedBy: array.endIndex)
                else {
                    let cut = array[st..<array.endIndex].joined()
                    handle(cut,true)
                    return
            }
            let cut = array[st..<end].joined()
            handle(cut, end == array.endIndex)
        }
    }

これにより、以前より高速に動作するようになりました。arrayが頻出しているのが気にくわないけど。。。
substringより、分解してjoinedした方が早いのは、swiftの内部実装のせいかな。

3
2
3

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
3
2