Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

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