1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Ruby] Enumerable#chunk{,_while}、Enumerable#slice_{before,after,when} の違い

Last updated at Posted at 2022-11-14

これは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]]
  1. https://docs.ruby-lang.org/ja/latest/class/Enumerable.html

  2. https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/chunk.html

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?