Rubyのビット演算子でarrayを操作する

こんにちは、hachi8833です。今回はRubyの小ネタです。

Qiitaで「RubyでArrayどうしを加算して一意にするのをuniqメソッド使わずにやる」という記事を見かけておっと思ったので、もう少し調べてみました。

[1] pry(main)> [1,2,3,1]|[2,3,88,4,4,6,7,23,41]
=> [1, 2, 3, 88, 4, 6, 7, 23, 41]

縦棒演算子|を使用することで、確かに2つのarray全体の重複が解消されました。arrayの内容の順序は保存されるので、.sortで改めてソートをかけることもできます。
この縦棒は何だろうと思ったら、基本的にrubyのビット論理和演算子として使われているものでした。

Rubyで使われる記号の意味

論理和演算子または類似のメソッド。二進数で 0011 | 0101 => 0111。

arrayで別のメソッドが用意されているようなので、ソースを開いてみました。

[29] pry(main)> show-source Array#|
From: array.c (C Method):
Owner: Array
Visibility: public
Number of lines: 19

static VALUE
rb_ary_or(VALUE ary1, VALUE ary2)
{
    VALUE hash, ary3;
    long i;

    ary2 = to_ary(ary2);
    hash = ary_make_hash(ary1);

    for (i=0; i<RARRAY_LEN(ary2); i++) {
        VALUE elt = RARRAY_AREF(ary2, i);
        if (!st_update(RHASH_TBL_RAW(hash), (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
            RB_OBJ_WRITTEN(hash, Qundef, elt);
        }
    }
    ary3 = rb_hash_values(hash);
    ary_recycle_hash(hash);
    return ary3;
}

ORがあるならANDもあるだろうと思ってやってみると、やはりビット論理和記号&を使用したメソッドがarrayにありました。

[33] pry(main)> [1,2,3,1]&[88,4,6,7,7,23,41]
=> []
[34] pry(main)> [1,2,3,4]&[88,4,6,7,7,23,41]
=> [4]

なおXOR記号の^メソッドはarrayにはありませんでした。

[35] pry(main)> [1,2,3,4]^[88,4,6,7,7,23,41]
NoMethodError: undefined method `^' for [1, 2, 3, 4]:Array
from (pry):29:in `__pry__'

当然ながら、arrayでない数字などに対して|や&を使用すると本来のビット演算が動き出してしまいます。

[3] pry(main)> 1|2
=> 3
[4] pry(main)> 2|3
=> 3
[5] pry(main)> 3|5
=> 7
[37] pry(main)> 3&2
=> 2
[38] pry(main)> 3&1
=> 1
[39] pry(main)> 3&4
=> 0

両方ともarrayであることが前提です。

[40] pry(main)> 3|[1,2,3]
TypeError: Array can't be coerced into Fixnum
from (pry):33:in `|'
[41] pry(main)> [1,2,3]|3
TypeError: no implicit conversion of Fixnum into Array
from (pry):34:in `|'
Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833

コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。
これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。
かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。
実は最近Go言語が好き。
仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

BPSアドベントカレンダー

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ