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: ...>