Ruby Tips!

RubyのTipsを紹介します

Marshalで配列やハッシュをディープコピーする

Object#dupObject#cloneで配列やハッシュを複製すると、配列やハッシュ自体は複製されるがその要素までは複製されない。これはシャローコピー(浅いコピー)と呼ばれる。

以下は配列を複製した時に、元の配列の要素を破壊的に変更すると、複製した配列にも影響が及ぶ例である。

a = ["foo", "bar", "baz"]
b = a.dup
a[0].upcase!
p a #=> ["FOO", "bar", "baz"]
p b #=> ["FOO", "bar", "baz"]

場合によってはシャローコピーでは都合が悪く、配列やハッシュの要素も含めてこれらのオブジェクトを完全に複製したい場合があるかもしれない。

そのような複製はディープコピー(深いコピー)と呼ばれ、RubyではmarshalライブラリのMarshal.dumpMarshal.loadを使うのが簡単である。

以下のコードは上記のコードをmarshalライブラリによるディープコピーで書き換えた例である。これなら元の配列の要素を破壊的に変更しても複製した配列に影響はない。

require 'marshal'

a = ["foo", "bar", "baz"]
b = Marshal.load(Marshal.dump(a))
a[0].upcase!
p a #=> ["FOO", "bar", "baz"]
p b #=> ["foo", "bar", "baz"]