Ruby_Array_62

この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。

class Array (Ruby 3.1 リファレンスマニュアル)

インスタンスメソッド

zip(*lists) -> [ [object] ]
zip(*lists) {|v1, v2, ...| ...} -> nil
  • 自身と引数に渡した配列の各要素からなる配列の配列を生成して返す
    • 生成される配列の要素数はselfの要素数と同じ
  • ブロック付きで呼び出した場合は、selfと引数に渡した配列の各要素を順番にブロックに渡す
  • listsに配列以外のオブジェクトを指定した場合、to_aryメソッドによる暗黙の型変換を試み、それに応答できない場合はeachメソッドんによる暗黙の型変換を試みる。配列以外の(暗黙の型変換が行えない)オブジェクトを指定するとTypeErrorが発生する
irb(main):001:0> [1, 2, 3].zip(['a', 'b', 'c'])
=> [[1, "a"], [2, "b"], [3, "c"]]

irb(main):002:0> [1, 2, 3].zip(['a', 'b', 'c'], [4, 5, 6])
=> [[1, "a", 4], [2, "b", 5], [3, "c", 6]]

irb(main):003:0> [1, 2, 3, 4, 5].zip(['a', 'b', 'c'], [4, 5, 6])
=> [[1, "a", 4], [2, "b", 5], [3, "c", 6], [4, nil, nil], [5, nil, nil]]
irb(main):001:0> arr = [1, 2, 3]
=> [1, 2, 3]

irb(main):002:0> brr = %w[a b c]
=> ["a", "b", "c"]

irb(main):003:0> crr = arr.zip(brr)
=> [[1, "a"], [2, "b"], [3, "c"]]

irb(main):004:0> brr[0].capitalize!
=> "A"

irb(main):005:0> crr
=> [[1, "A"], [2, "b"], [3, "c"]]
irb(main):001:0> [1, 2, 3].zip
=> [[1], [2], [3]]

irb(main):002:0> [1, 2, 3].zip([])
=> [[1, nil], [2, nil], [3, nil]]

irb(main):003:0> [].zip([1, 2, 3])
=> []

# memo
# この挙動は覚えておきたい
irb(main):001:0> [1, 2, 3].zip([4, 5, 6], [7, 8, 9]) { |arr| pp arr }
[1, 4, 7]
[2, 5, 8]                                                                                                
[3, 6, 9]                                                                                                
=> nil                                                                                                   
irb(main):002:0> [1, 2, 3].zip([4, 5, 6], [7, 8, 9]) { |v1, v2, v3| pp v2 }
4
5                                                                                                        
6                                                                                                        
=> nil
irb(main):001:0> [1, 2, 3].zip('a')
(irb):1:in `zip': wrong argument type String (must respond to :each) (TypeError)
        from (irb):1:in `<main>'
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'
self | other -> Array
  • 集合の和演算。両方の配列いずれかに含まれる要素をすべて含む新しい配列を返す
    • 重複する要素は取り除かれる
    • 重複判定はObject#eql?とObject#hashにより行われる
    • 新しい配列における要素の順はselfにおける要素の順と同じ
  • otherには配列以外のオブジェクトを指定した場合は to_ary メソッドによる暗黙の型変換を試みる。配列以外の(暗黙の型変換が行えない)オブジェクトを指定した場合TypeErrorが発生する
irb(main):001:0> [1, 2, 3, 1] | [7, 5, 3]
=> [1, 2, 3, 7, 5]

irb(main):002:0> [1, 2, 3, 1, 1.0] | ['1']
=> [1, 2, 3, 1.0, "1"]

irb(main):003:0> [1, 2, 3] | 'a'
(irb):1:in `|': no implicit conversion of String into Array (TypeError)
        from (irb):1:in `<main>'
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'

Ruby_Array_61

この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。

class Array (Ruby 3.1 リファレンスマニュアル)

インスタンスメソッド

uniq -> Array
uniq! -> self | nil
uniq {|item| ... } -> Array
uniq! {|item| ... } -> self | nil
  • uniqは配列から重複した要素を取り除いた新しい配列を返す
  • uniq!は削除を破壊的に行い、削除が行われた場合はselfを、そうでなければnilを返す
    • この挙動は覚えておきたい
  • 要素の重複判定はObject#eql?によって行われる
  • ブロックが与えられた場合、ブロックが返した値が重複した要素を取り除いた配列を返す
  • 要素を先頭から巡っていき、最初に出現したものが残る
irb(main):001:0> arr = [1, 2, 1]
=> [1, 2, 1]

irb(main):002:0> brr = arr.uniq
=> [1, 2]

irb(main):003:0> arr
=> [1, 2, 1]

irb(main):004:0> brr
=> [1, 2]
irb(main):001:0> arr = [1, 2, 1]
=> [1, 2, 1]

irb(main):002:0> brr = arr.uniq!
=> [1, 2]

irb(main):003:0> arr
=> [1, 2]

irb(main):004:0> brr
=> [1, 2]
irb(main):001:0> [1, 2, 3].uniq
=> [1, 2, 3]

irb(main):002:0> [1, 2, 3].uniq!
=> nil
irb(main):001:0> [1, 1.0, '1'].uniq
=> [1, 1.0, "1"]

irb(main):002:0> [1, 1.0, '1'].uniq { |v| v.to_i }
=> [1]
irb(main):001:0> v1 = 'e'
=> "e"

irb(main):002:0> v2 = 'e'
=> "e"

irb(main):003:0> arr = [v1, v2]
=> ["e", "e"]

irb(main):004:0> brr = arr.uniq
=> ["e"]

irb(main):005:0> v2.capitalize!
=> "E"

irb(main):006:0> brr
=> ["e"]

irb(main):007:0> v1.capitalize!
=> "E"

irb(main):008:0> brr
=> ["E"]

# memo
# 覚えておきたい
values_at(*selectors) -> Array
  • 引数で指定されたインデックスに対応する要素を配列で返す
    • インデックスに対応する値がなければnilが要素になる
  • インデックスは整数もしくは整数のRangeで指定する
irb(main):001:0> arr = %w[a b c d e]
=> ["a", "b", "c", "d", "e"]

irb(main):002:0> arr.values_at(0, 2, 4)
=> ["a", "c", "e"]

irb(main):003:0> arr.values_at(0, 4, 2)
=> ["a", "e", "c"]

irb(main):004:0> arr.values_at(0, 0, 0)
=> ["a", "a", "a"]

irb(main):005:0> arr.values_at(0, 4, 10)
=> ["a", "e", nil]

irb(main):006:0> arr.values_at(-4, -1, -100)
=> ["b", "e", nil]

irb(main):007:0> arr.values_at(0..2)
=> ["a", "b", "c"]

irb(main):008:0> arr.values_at(0..10)
=> ["a", "b", "c", "d", "e", nil, nil, nil, nil, nil, nil]

irb(main):009:0> arr.values_at(5..6)
=> [nil, nil]

irb(main):010:0> arr.values_at(6..7)
=> [nil, nil]

irb(main):011:0> arr.values_at(0, 1..4, 2)
=> ["a", "b", "c", "d", "e", "c"]

# memo
# 引数を前から順に処理している感じ
irb(main):001:0> arr = %w[a b c d e]
=> ["a", "b", "c", "d", "e"]

irb(main):002:0> arr.values_at(1.0)
=> ["b"]

irb(main):003:0> arr.values_at(1.8)
=> ["b"]

irb(main):004:0> arr.values_at('1.0')
(irb):4:in `values_at': no implicit conversion of String into Integer (TypeError)
        from (irb):4:in `<main>'                                      
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'  
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'

Ruby_Array_60

この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。

class Array (Ruby 3.1 リファレンスマニュアル)

インスタンスメソッド

transpose -> Array
  • 自身を行列と見立てて、行列の転置を行い、転置した配列を生成して返す
    • 空の配列に対しては空の配列を生成して返す
  • 一次元の配列に対してはTypeErrorが、各要素のサイズが不揃いな配列に対してはIndexErrorが発生する
# 1 2
# 3 4
# 5 6
# ↓
# 1 3 5
# 2 4 6

irb(main):001:0> arr = [[1, 2], [3, 4], [5, 6]]
=> [[1, 2], [3, 4], [5, 6]]

irb(main):002:0> arr.transpose
=> [[1, 3, 5], [2, 4, 6]]

irb(main):003:0> arr
=> [[1, 2], [3, 4], [5, 6]]

irb(main):004:0> arr.transpose.transpose
=> [[1, 2], [3, 4], [5, 6]]

irb(main):005:0> [].transpose
=> []
irb(main):001:0> arr = [['a', 'b'], ['c', 'd']]
=> [["a", "b"], ["c", "d"]]

irb(main):002:0> brr = arr.transpose
=> [["a", "c"], ["b", "d"]]

irb(main):003:0> arr[0][0].capitalize!
=> "A"

irb(main):004:0> arr
=> [["A", "b"], ["c", "d"]]

irb(main):005:0> brr
=> [["A", "c"], ["b", "d"]]
irb(main):001:0> [1, 2, 3].transpose
(irb):1:in `transpose': no implicit conversion of Integer into Array (TypeError)
        from (irb):1:in `<main>'                                            
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'        
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'  

irb(main):002:0> [[1, 2], [3, 4, 5]].transpose
(irb):2:in `transpose': element size differs (3 should be 2) (IndexError)
        from (irb):2:in `<main>'                                                         
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'                     
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>' 
union(*other_arrays) -> Array
  • 集合の和演算。重複する要素は取り除かれる
    • 重複判定はObject#eql?とObject#hashによって行われる
irb(main):001:0> [1, 'a', 'b'].union([1, 1.0, '1', 'a', 'A'])
=> [1, "a", "b", 1.0, "1", "A"]

irb(main):002:0> [1, 'a', 'b'].union([1, 1.0, '1', 'a', 'A'], ['c'])
=> [1, "a", "b", 1.0, "1", "A", "c"]

irb(main):003:0> [1, 'a', 'b'].union([])
=> [1, "a", "b"]

irb(main):004:0> [1, 'a', 'b'].union
=> [1, "a", "b"]
irb(main):001:0> v = 'a'
=> "a"

irb(main):002:0> [v].union([v])
=> ["a"]

irb(main):003:0> [v].union([v.capitalize!])
=> ["A"]

irb(main):004:0> ['a'].union(['a'.capitalize!])
=> ["a", "A"]
[7] pry(main)> show-source Array#union

From: array.c (C Method):
Owner: Array
Visibility: public
Signature: union(*arg1)
Number of lines: 29

static VALUE
rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
{
    int i;
    long sum;
    VALUE hash, ary_union;

    sum = RARRAY_LEN(ary);
    for (i = 0; i < argc; i++) {
        argv[i] = to_ary(argv[i]);
        sum += RARRAY_LEN(argv[i]);
    }

    if (sum <= SMALL_ARRAY_LEN) {
        ary_union = rb_ary_new();

        rb_ary_union(ary_union, ary);
        for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);

        return ary_union;
    }

    hash = ary_make_hash(ary);
    for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);

    ary_union = rb_hash_values(hash);
    ary_recycle_hash(hash);
    return ary_union;
}

[8] pry(main)> show-source Array#|

From: array.c (C Method):
Owner: Array
Visibility: public
Signature: |(arg1)
Number of lines: 20

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

    ary2 = to_ary(ary2);
    if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
        ary3 = rb_ary_new();
        rb_ary_union(ary3, ary1);
        rb_ary_union(ary3, ary2);
        return ary3;
    }

    hash = ary_make_hash(ary1);
    rb_ary_union_hash(hash, ary2);

    ary3 = rb_hash_values(hash);
    ary_recycle_hash(hash);
    return ary3;
}

# memo
# Array#unionとArray#|の内部実装が若干違う
# Array#unionは配列を複数受け取るからそこの対応の差なのかな?内部実装はまだ読み解いていない

Ruby_Array_59

この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。

class Array (Ruby 3.1 リファレンスマニュアル)

インスタンスメソッド

to_a -> Array
  • selfを返す
    • ただしArray のサブクラスのインスタンスに対して呼ばれたときは自身をArrayに変換したものを返す
irb(main):001:0> arr = []
=> []

irb(main):002:0> arr.to_a.class
=> Array
irb(main):001:0> class Foo < Array
irb(main):002:0> end
=> nil

irb(main):003:0> foo = Foo.new
=> []

irb(main):004:0> foo.to_a.class
=> Array
to_ary -> self
  • selfをそのまま返す
irb(main):001:0> arr = []
=> []

irb(main):002:0> arr.to_a.class
=> Array
irb(main):001:0> class Foo < Array
irb(main):002:0> end
=> nil

irb(main):003:0> foo = Foo.new
=> []

irb(main):004:0> foo.to_ary.class
=> Foo
to_h -> Hash
to_h { block } -> Hash
  • selfを[key, value]のペアの配列として解析し、結果をHashにして返す
    • [[k1, v1], [k2, v2], ...]の形式
  • ブロックを指定すると、配列の各要素でブロックを呼び出しその結果をペアとして利用する
irb(main):001:0> [['a', 1]].to_h
=> {"a"=>1}

irb(main):002:0> [['a', 1], ['b', 2]].to_h
=> {"a"=>1, "b"=>2}

irb(main):003:0> [['a', 1], ['b', 2], ['c', nil]].to_h
=> {"a"=>1, "b"=>2, "c"=>nil}
irb(main):002:0> ['a', 1].to_h
(irb):2:in `to_h': wrong element type String at 0 (expected array) (TypeError)
        from (irb):2:in `<main>'          
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'

irb(main):001:0> [['a', 1], ['b']].to_h
(irb):1:in `to_h': wrong array length at 1 (expected 2, was 1) (ArgumentError)
        from (irb):1:in `<main>'                                                
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'            
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'
irb(main):001:0> [['a', 1], ['b', 2]].to_h { |k, v| [k, v] }
=> {"a"=>1, "b"=>2}

irb(main):002:0> [['a', 1], ['b', 2]].to_h { |k, v| [k.upcase, v + 100] }
=> {"A"=>101, "B"=>102}

メモ

  • to_aryを今知った

Ruby_Array_58

この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。

class Array (Ruby 3.1 リファレンスマニュアル)

インスタンスメソッド

take(n) -> Array
  • 配列の先頭からn要素を配列として返す
    • 自身を破壊的には変更しない
irb(main):001:0> arr = %w[a b c d e]
=> ["a", "b", "c", "d", "e"]

irb(main):002:0> arr.take(3)
=> ["a", "b", "c"]

irb(main):003:0> arr
=> ["a", "b", "c", "d", "e"]

irb(main):004:0> arr.take(0)
=> []

irb(main):005:0> arr.take(10)
=> ["a", "b", "c", "d", "e"]
irb(main):001:0> arr = %w[a b c d e]
=> ["a", "b", "c", "d", "e"]

irb(main):002:0> arr.take(1.0)
=> ["a"]

irb(main):003:0> arr.take(1.5)
=> ["a"]

irb(main):004:0> arr.take('1')
(irb):3:in `take': no implicit conversion of String into Integer (TypeError)
        from (irb):3:in `<main>'                            
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'

irb(main):005:0> arr.take(-1)
(irb):4:in `take': attempt to take negative size (ArgumentError)
        from (irb):4:in `<main>'                            
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'
pry(main)> show-source Array#take

From: array.c (C Method):
Owner: Array
Visibility: public
Signature: take(arg1)
Number of lines: 9

static VALUE
rb_ary_take(VALUE obj, VALUE n)
{
    long len = NUM2LONG(n);
    if (len < 0) {
        rb_raise(rb_eArgError, "attempt to take negative size");
    }
    return rb_ary_subseq(obj, 0, len);
}


pry(main)> show-source Array#slice

From: array.c (C Method):
Owner: Array
Visibility: public
Signature: slice(*arg1)
Number of lines: 9

VALUE
rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
{
    rb_check_arity(argc, 1, 2);
    if (argc == 2) {
        return rb_ary_aref2(ary, argv[0], argv[1]);
    }
    return rb_ary_aref1(ary, argv[0]);
}


# memo
# 内部ではslice(0, n)と同じことをしていそうだ
# https://github.com/ruby/ruby/blob/a51f30c6712798fc07e57f692d0d0e5ccc59acf1/array.c#L1885-L1893
take_while -> Enumerator
take_while {|element| ... } -> Array
  • 配列の要素を順に偽になるまでブロックで評価し、最初に偽になった要素の手前の要素までを配列として返す
    • 自身を破壊的に変更しない
  • ブロックを省略した場合はEnumeratorを返す
irb(main):001:0> arr = [1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]

irb(main):002:0> arr.take_while { |v| v < 3 }
=> [1, 2]

irb(main):003:0> arr
=> [1, 2, 3, 4, 5]

irb(main):004:0> arr.take_while { |v| v < 1 }
=> []

irb(main):005:0> arr.take_while { |v| v < 10 }
=> [1, 2, 3, 4, 5]
irb(main):001:0> arr = [1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]

irb(main):002:0> enum = arr.take_while
=> #<Enumerator: ...>

irb(main):003:0> enum.each { |v| v < 3 }
=> [1, 2]

irb(main):004:0> arr.unshift(0)
=> [0, 1, 2, 3, 4, 5]

irb(main):005:0> enum
=> #<Enumerator: ...>

irb(main):006:0> enum.each { |v| v < 3 }
=> [0, 1, 2]

メモ

irbの表示が変わっている。要素が少ないときは3.0.0のような表示のほうが個人的にはわかりやすくてよかったかも。

$ ruby -v
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin18]

$ irb

irb(main):001:0> [1, 2, 3].keep_if
=> #<Enumerator: [1, 2, 3]:keep_if>

$ rbenv local 3.1.0

$ ruby -v
ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x86_64-darwin18]

$ irb

irb(main):001:0> [1, 2, 3].keep_if
=> #<Enumerator: ...>

Ruby_Array_57

この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。

class Array (Ruby 3.1 リファレンスマニュアル)

インスタンスメソッド

sum(init=0) -> object
sum(init=0) {|e| expr } -> object
  • 要素の合計を返す
    • [e1, e2, e3].sumはinit + e1 + e2 + e3を返す
  • ブロックが与えられた場合、加算する前に各要素にブロックが適用される
  • 配列が空の場合、initを返す
  • initを明示的に指定すると数値以外のオブジェクトにも使える
  • "+"メソッドが再定義されている場合、Array#sumは再定義を無視することがある
irb(main):001:0> [1, 2, 3].sum
=> 6

irb(main):002:0> [1, 2, 3].sum(4)
=> 10

irb(main):003:0> [].sum
=> 0

irb(main):004:0> [].sum(10)
=> 10

irb(main):005:0> [1, 2, 3].sum { |v| v * 10 }
=> 60
irb(main):001:0> %w[a b c].sum
(irb):1:in `+': String can't be coerced into Integer (TypeError)
        from (irb):1:in `sum'                                           
        from (irb):1:in `<main>'                                        
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'    
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'  

irb(main):002:0> %w[a b c].sum('')
=> "abc"

# memo
# initを明示的に指定する必要あり
# %w[a b c].joinのほうが高速
irb(main):001:0> [[1], [2, 3], [4]].sum
(irb):3:in `+': Array can't be coerced into Integer (TypeError)
        from (irb):3:in `sum'                                                           
        from (irb):3:in `<main>'                                                        
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'                    
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>' 

irb(main):002:0> [[1], [2, 3], [4]].sum([])
=> [1, 2, 3, 4]

# memo
# initを明示的に指定する必要あり
# [[1], [2, 3], [4]].flattenのほうが高速
$ cat sample1.rb
class Integer
  def +(arg)
    10
  end
end

pp 1 + 2 + 3

pp [1, 2, 3].sum

$ bundle exec ruby sample1.rb
10
6

# "+"を再定義したが、sumで無視されている
# こういう理解で合ってる?
$ cat sample2.rb
class Foo
  def +(arg)
    self
  end
end

foo = Foo.new

pp foo

pp [foo, foo, foo].sum(foo)

$ bundle exec ruby sample2.rb
#<Foo:0x000000010e06c840>
#<Foo:0x000000010e06c840>

メモ

  • sumにinit設定できるのを今知った

Ruby_Array_56

この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。

class Array (Ruby 3.1 リファレンスマニュアル)

インスタンスメソッド

sort -> Array
sort! -> self
sort {|a, b| ... } -> Array
sort! {|a, b| ... } -> self
  • 配列の内容をソートする
  • sortはソートされた配列を生成して返す
  • sort!はselfを破壊的にソートしてselfを返す
  • ブロックとともに呼び出されたときは、比較をブロックを用いて行う
    • ブロックに2つの要素を引数として与えて評価する
    • ブロックは<=>演算子と同様に整数を返すことが期待されている
      • 第一引数が大きいなら正の整数、等しいなら0、小さいなら負の整数を返す必要がある。比較できないときはnilを返す。
irb(main):001:0> arr = %w[e c a b d]
=> ["e", "c", "a", "b", "d"]

irb(main):002:0> arr.sort
=> ["a", "b", "c", "d", "e"]

irb(main):003:0> arr
=> ["e", "c", "a", "b", "d"]

irb(main):004:0> arr.sort!
=> ["a", "b", "c", "d", "e"]

irb(main):005:0> arr
=> ["a", "b", "c", "d", "e"]
irb(main):001:0> arr = %w[10 3 6 20 2 1]
=> ["10", "3", "6", "20", "2", "1"]

irb(main):002:0> arr.sort
=> ["1", "10", "2", "20", "3", "6"]

irb(main):003:0> arr.map(&:to_i).sort
=> [1, 2, 3, 6, 10, 20]

irb(main):004:0> arr.sort { |a, b| a.to_i <=> b.to_i }
=> ["1", "2", "3", "6", "10", "20"]

irb(main):005:0> arr
=> ["10", "3", "6", "20", "2", "1"]

irb(main):006:0> arr.sort! { |a, b| a.to_i <=> b.to_i }
=> ["1", "2", "3", "6", "10", "20"]

irb(main):007:0> arr
=> ["1", "2", "3", "6", "10", "20"]

# パフォーマンスについてはsort_byの項目も要参照
# https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/sort_by.html
irb(main):001:0> %w[10 3 6 20 2 1].sort { |a, b| -1 }
=> ["10", "3", "6", "20", "2", "1"]

irb(main):002:0> %w[z b h a].sort { |a, b| -1 }
=> ["z", "b", "h", "a"]

# memo
# 第一引数のほうが小さいことを意味する負の整数を常に返しているのでソートされていない
irb(main):001:0> %w[z b h a].sort { |a, b| nil }
(irb):1:in `sort': comparison of String with String failed (ArgumentError)
        from (irb):1:in `<main>'
        from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load'
        from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'

sort_by! -> Enumerator

sort_by! {|item| ... } -> self

  • sort_byの破壊的バージョン
  • ブロックを省略した場合はEnumeratorを返す
irb(main):001:0> arr = %w[ab z car]
=> ["ab", "z", "car"]

irb(main):002:0> arr.sort_by! { |v| v.size }
=> ["z", "ab", "car"]

irb(main):003:0> arr
=> ["z", "ab", "car"]
irb(main):001:0> enum = %w[ab z car].sort_by!
=> #<Enumerator: ...>

irb(main):002:0> enum.each { |v| v.size }
=> ["z", "ab", "car"]

irb(main):003:0> enum.each { |v| -v.size }
=> ["car", "ab", "z"]