或るプログラマの開発日記

日々の勉強したことの備忘録なんかに使っていきます

Rubyの文字列連結メモ

どうも、パイソンです。

今日は、Rubyの文字列連結で少しハマった事をメモしておきます。

Rubyの文字列連結演算子

まずは、基本から。

Rubyで文字列を連結する方法には、+演算子を使う方法と、<<演算子を使う方法があります。

#文字列連結テスト
str1 = "ABC" + "DEF"
puts str1 #"ABCDEF"と出力
str2 = "abc" << "def"
puts str2 #"abcdef"と出力

+演算子と<<演算子の違い

どちらも文字列を連結しているだけのように見えますが、

  • +演算子は連結した新たなオブジェクトを返す。
  • <<演算子は左辺のオブジェクトを直接書き換える。

という点で違いがあります。

いろんなサイトで調べてみたところ、「+演算子は処理速度が遅い。<<演算子は処理速度が速いけどオブジェクトを破壊するので気をつけましょう。」という感じのようです。

何に気をつけるの?

じゃぁ、オブジェクトを書き換える事で実際どんな事が起きるの?ということで少しサンプルを組んでみました。処理内容は、"A","B","C"の文字をn個繋げてできる全ての文字列の組み合わせを出力するというものです。

#+演算子で連結するVer
def func1(str, depth)
  if depth == 0
    puts str
    return
  end
  ["A", "B", "C"].each do |c|
    func1(str + c, depth -1)
  end
end

puts "func1を実行してみた結果"
func1("", 2)

実行結果

func1を実行してみた結果
AA
AB
AC
BA
BB
BC
CA
CB
CC


このプログラムの+演算子を<<に変更してみましょう。

#<<演算子で連結するVer
def func2(str, depth)
  if depth == 0
    puts str
    return
  end
  ["A", "B", "C"].each do |c|
    func2(str << c, depth -1)
  end
end

puts "func2を実行してみた結果"
func2("", 2)

実行結果

func2を実行してみた結果
AA
AAB
AABC
AABCBA
AABCBAB
AABCBABC
AABCBABCCA
AABCBABCCAB
AABCBABCCABC

と、まあ前の結果とは大違いの結果。。

要は再帰処理を使ってオブジェクトをスタックに積んでるつもりが、<<演算子を使ったのでひたすら一点のオブジェクトを書き換えてただけでした、というオチ。

雑感

当初Rubyおぼえたての私は、「<<のほうが早いんじゃん!」と単純に考えてましたが、やはりそれぞれの違いを理解して状況に応じ適切に使い分けるようにしないといけませんね。