こんにちは、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のビット論理和演算子として使われているものでした。
論理和演算子または類似のメソッド。二進数で 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 `|'