LoginSignup
17
8

More than 5 years have passed since last update.

Swiftで文字を任意の数繰り返した文字列にしたいときはそれ用のメソッドがある

Last updated at Posted at 2018-06-06

結論

Xcode8(Swift3ぐらい?)からStringに文字列を繰り返すメソッドがあったのでこれが使える

let s = String(repeating: "ab", count: 10)
print(s)
// Prints "abababababababababab"

Appleのリファレンス Documentation > Swift > String > init(repeating:count:)
https://developer.apple.com/documentation/swift/string/2427723-init

はじめに

文字列を規定以上に増やしてエラーになるような処理のテストコードを書きたかった。

rubyだと次のように書ける。

"a" * 2 # => "aa"

そのため、Swift 4.1でも同じようなことをやろうと、何も考えずにオペレータオーバーライドでのそれっぽい考えとして次のようなのがあると思う

import Foundation

func * (left: String, right: Int) -> String {
    var total = ""
    (0..<right).forEach { _ in
        total += left
    }
    return total
}

print("a" * 2)         // => "aa"
print(("a" * 2).count) // => 2

しかし、これだとStringオブジェクトをループごとに+=で作成してしまっていて無駄な気がする(例えば* 2000にすると2,000のStringが作られてる気がする)。テストで使いたい、無駄なコピーしてでも手に入れたいわけだけど、なんだか気になる。

ここで、Appleのリファレンスを調べているとString(repeating: "ab", count: 10)があることがわかった。

Swiftのコードは設計図共有サイトにあるので見てみる。まず、swift4.1のブランチ

  public init(repeating repeatedValue: String, count: Int) {
    if count == 0 {
      self = ""
      return
    }
    precondition(count > 0, "Negative count not allowed")
    let s = repeatedValue
    self = String(_storage: _StringBuffer(
        capacity: s._core.count * count,
        initialSize: 0,
        elementWidth: s._core.elementWidth))
    for _ in 0..<count {
      self += s
}

なるほどねー、たしかにcountが0のときとかマイナスのときの処理は必要だよねーと思ったものの、最後に結局+=で文字列を生成している様子。

ただ、swiftの最新2018-06-06のtag(swift-DEVELOPMENT-SNAPSHOT-2018-06-05-a)に切り替えてみると、ループで文字列を結合しているわけではないみたい🤔

17
8
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
17
8