これは2016年くらいに るりま1を見て書いたメモです。今のるりまは充実していて、嬉しいです。下記の内容は現在の Ruby でも変わっていないので自分用に投稿します。
ruby の Enumerable モジュールには、似たようなメソッド
- chunk
- chunk_while
- slice_before
- slice_after
- slice_when
があります。
このうち、chunk_while、slice_after、slice_when は Ruby 2.3 から使用可能です。
形式
chunk {|elt| key } -> Enumerator<key, chunk>
chunk_while {|elt_before, elt_after| bool } -> Enumerator<chunk>
slice_before {|elt| bool } -> Enumerator<chunk>
slice_before(pattern) -> Enumerator<chunk>
slice_after {|elt| bool } -> Enumerator<chunk>
slice_after(pattern) -> Enumerator<chunk>
slice_when {|elt_before, elt_after| bool } -> Enumerator<chunk>
説明
- chunk
- ブロックの評価値が同じ値が続くものを一つのチャンクにする
- (評価値が異なる値になるところで区切る)
- chunk_while
- 隣り合う要素を引数にしてブロックの評価値が真なら一つのチャンクにする
- (偽になるところで区切る)
- slice_before
- ブロックの評価値が真になった要素の直前で区切る
- (その要素をチャンクの先頭とみなす)
- slice_after
- ブロックの評価値が真になった要素の直後で区切る
- (その要素をチャンクの末尾とみなす)
- slice_when
- 隣り合う要素を引数にしてブロックの評価値が真になるところで区切る
- (偽なら一つのチャンクにする)
返される Enumerator の chunk
は配列。
Enumerable#chunk だけ、返される Enumerator の形式が違います。
Enumerable#chunk はブロックの特別な評価値として nil
もしくは :_separator
と :_alone
があります。るりま を参照2してください。
Enumerable#slice_before は最初の要素もブロックを呼び出すが評価値は無視されます。
Enumerable#slice_after は最後の要素もブロックを呼び出すが評価値は無視されます。
Enumerable#slice_before と Enumerable#slice_after の pattern
は {|elt| pattern === elt }
の代わりです。
引数 initial_state
を渡す形式は deprecated なため除外しています。
ブロックを呼ぶ回数
メソッド | ブロックを呼ぶ回数 |
---|---|
chunk | length |
chunk_while | length - 1 |
slice_before | length |
slice_after | length |
slice_when | length - 1 |
要素がブロックパラメータになる回数
メソッド | 要素がブロックパラメータになる回数 |
---|---|
chunk | 1* |
chunk_while | 1 2* 1 |
slice_before | 1* |
slice_after | 1* |
slice_when | 1 2* 1 |
Enumerable#slice_before と Enumerable#slice_after の関係
ary = [0, 2, 4, 1, 2, 4, 5, 3, 1, 4, 2]
p ary.slice_before(&:even?).to_a
p ary.slice_when {|_prev, curr| curr.even? }.to_a
p ary.chunk_while {|_prev, curr| curr.odd? }.to_a
#>> [[0], [2], [4, 1], [2], [4, 5, 3, 1], [4], [2]]
p ary.slice_before(&:odd?).to_a
p ary.slice_when {|_prev, curr| curr.odd? }.to_a
p ary.chunk_while {|_prev, curr| curr.even? }.to_a
#>> [[0, 2, 4], [1, 2, 4], [5], [3], [1, 4, 2]]
p ary.slice_after(&:even?).to_a
p ary.slice_when {|curr, _next| curr.even? }.to_a
p ary.chunk_while {|curr, _next| curr.odd? }.to_a
#>> [[0], [2], [4], [1, 2], [4], [5, 3, 1, 4], [2]]
p ary.slice_after(&:odd?).to_a
p ary.slice_when {|curr, _next| curr.odd? }.to_a
p ary.chunk_while {|curr, _next| curr.even? }.to_a
#>> [[0, 2, 4, 1], [2, 4, 5], [3], [1], [4, 2]]