Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

chunkメソッドで配列を意味合い単位で切り分ける

参考もと様の記事を眺めていたところ、chunkというメソッドを発見。
チャンクという位ですから、意味合いレベルのカタマリを作ってくれるものと考えられます。
試しに公式を見に行ったところ

要素を前から順にブロックで評価し、その結果によって 要素をチャンクに分けた(グループ化した)要素を持つ Enumerator を返します。

とのこと。サンプルとして、以下のように偶数か判定して多重配列をつくるものが...

[3,1,4,1,5,9,2,6,5,3,5].chunk {|n| n.even? }.each {|even, ary| p [even, ary] }
#=> [false, [3, 1]]
# [true, [4]]
# [false, [1, 5, 9]]
# [true, [2, 6]]

な、なにこれ...?

遊んでみる

chunk {|a,b| key}

> %w(a b c).chunk {|i| i}.each { |a, b| p a,b }
"a"
["a"]
"b"
["b"]
"c"
["c"]
=> nil

chunkに渡すブロックで小分け条件を指定、

> %w(as you like).chunk {|i| i.length > 3}.each do |a, b| p [a, b] end
[false, ["as", "you"]]
[true, ["like"]]
=> nil

ブロックなのでprocオブジェクトを渡す事もできます。
chunk_with_objectなんてのは流石に無さそうですが。

> (1..10).map.chunk(&:odd?).each  {|a, b| p [a, b]}
[true, [1]]
[false, [2]]
[true, [3]]
[false, [4]]
[true, [5]]
[false, [6]]
[true, [7]]
[false, [8]]
[true, [9]]
[false, [10]]
=> nil

chunk(initial_state){|a,b| key}

enum.chunk(initial_state) {|elt, state| key }.each {|key, ary| ... }

とあるように、初期値を渡す事も可能です。

> %w(a b c d).chunk('c'){|elt,state|elt == state}.each {|key, ary| p key,ary}

状態遷移図のような複雑な事も出来ます。

> flag = 1; ('a'..'z').chunk(['c','w']){|elt,state| \
case flag
when 1 then elt == state[0]; flag = 2
when 2 then elt == state[1]
end
}.each{|a,b| p a,b}
2
["a"]
false
["b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v"]
true
["w"]
false
["x", "y", "z"]
=> nil