ふと気付いた
先日こういう記事を書きました。
Ruby - ブロックパラメータを複数取るEnumerableメソッドのあとにEnumeratorメソッドを重ねたときのブロックパラメータの指定方法(余談としてブロックローカル変数の宣言のこと) - Qiita
もしや、eachでも複数のブロックパラメータが取れる?
やってみた
配列の各要素がStringではなく2要素のArray。
ブロックパラメータを2つ指定すれば、それぞれArray要素が代入されるはず。
pry(main)> num = (0..9).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
pry(main)> pronoun = %w[zero one two three four five six seven eight nine]
=> ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
pry(main)> num_pronoun = num.zip(pronoun)
=> [[0, "zero"],
[1, "one"],
[2, "two"],
[3, "three"],
[4, "four"],
[5, "five"],
[6, "six"],
[7, "seven"],
[8, "eight"],
[9, "nine"]]
pry(main)> num_pronoun.each{ |i, word| puts "#{i}: #{word}" };
0: zero
1: one
2: two
3: three
4: four
5: five
6: six
7: seven
8: eight
9: nine
うまくいきました^_^
配列がフラットだと(念のため確認)
pry(main)> num_pronoun_flat = num_pronoun.flatten
=> [0, "zero", 1, "one", 2, "two", 3, "three", 4, "four", 5, "five", 6, "six", 7, "seven", 8, "eight", 9, "nine"]
pry(main)> num_pronoun_flat.each{ |i, word| puts "#{i}: #{word}" };
0:
zero:
1:
one:
2:
two:
3:
three:
4:
four:
5:
five:
6:
six:
7:
seven:
8:
eight:
9:
nine:
つまりi
に値が入ってword
に入らなかった。
Enumerator#each
は要素を一つずつ取り出すので、当然の結果でしたね。配列やハッシュなど、オブジェクトとして括られている必要があるわけで。
ということで
いままでは、いちいち
num_pronoun.each do |i_word|
i, word = i_word
puts "#{i}: #{word}"
end
というように、ブロックパラメータからブロック内の変数に代入していたのですが、この手間を省いて
num_pronoun.each do |i, word|
puts "#{i}: #{word}"
end
とできる。ありがたいです。
複雑な要素のeach
そういえば、上記した記事では、丸括弧で括れば要素の中の要素が取得できましたね。
ということで、試してみましょう。
[数字, [英語, 漢数字]]
pry(main)> eng = %w[zero one two three four five six seven eight nine]
=> ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
pry(main)> kanji = %w[零 一 二 三 四 五 六 七 八 九]
=> ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
pry(main)> lang = eng.zip(kanji)
=> [["zero", "零"],
["one", "一"],
["two", "二"],
["three", "三"],
["four", "四"],
["five", "五"],
["six", "六"],
["seven", "七"],
["eight", "八"],
["nine", "九"]]
pry(main)> num_lang = num.zip(lang)
=> [[0, ["zero", "零"]],
[1, ["one", "一"]],
[2, ["two", "二"]],
[3, ["three", "三"]],
[4, ["four", "四"]],
[5, ["five", "五"]],
[6, ["six", "六"]],
[7, ["seven", "七"]],
[8, ["eight", "八"]],
[9, ["nine", "九"]]]
これで一要素を
[数字, [英語, 漢数字]]
という入れ子構造にできました。
|i, (eng, kanji)|
ではeachのブロックパラメータを|i, (eng, kanji)|
としてみましょう。
pry(main)> num_lang.each{ |i, (eng, kanji)| puts "#{i}: #{eng} / #{kanji}" };
0: zero / 零
1: one / 一
2: two / 二
3: three / 三
4: four / 四
5: five / 五
6: six / 六
7: seven / 七
8: eight / 八
9: nine / 九
- i: 数字
- eng: 英語
- kanji: 漢数字
と指定できていますね。
|i, eng, kanji|
では続いて|i, eng, kanji|
で指定しましょう。
pry(main)> num_lang.each{ |i, eng, kanji| puts "#{i}: #{eng} / #{kanji}" };
0: ["zero", "零"] /
1: ["one", "一"] /
2: ["two", "二"] /
3: ["three", "三"] /
4: ["four", "四"] /
5: ["five", "五"] /
6: ["six", "六"] /
7: ["seven", "七"] /
8: ["eight", "八"] /
9: ["nine", "九"] /
ということで
- i: 数字
- eng: [英語, 漢数字]
- kanji: nil
と解釈されてしまっています。
{ 数字 => [英語, 漢数字] }
続いて、要素の中にハッシュを組み合わせた場合を見てみます。
(ほぼ同じになるでしょうが)
前準備
pry(main)> num_to_lang_pair = num_lang.inject({}){ |hash, (i, a)| hash[i] = a; hash }
=> {0=>["zero", "零"],
1=>["one", "一"],
2=>["two", "二"],
3=>["three", "三"],
4=>["four", "四"],
5=>["five", "五"],
6=>["six", "六"],
7=>["seven", "七"],
8=>["eight", "八"],
9=>["nine", "九"]}
|i, (eng, kanji)|
pry(main)> num_to_lang_pair.each{ |i, (eng, kanji)| puts "#{i}: #{eng} / #{kanji}" };
0: zero / 零
1: one / 一
2: two / 二
3: three / 三
4: four / 四
5: five / 五
6: six / 六
7: seven / 七
8: eight / 八
9: nine / 九
|i, eng, kanji|
pry(main)> num_to_lang_pair.each{ |i, eng, kanji| puts "#{i}: #{eng} / #{kanji}" };
0: ["zero", "零"] /
1: ["one", "一"] /
2: ["two", "二"] /
3: ["three", "三"] /
4: ["four", "四"] /
5: ["five", "五"] /
6: ["six", "六"] /
7: ["seven", "七"] /
8: ["eight", "八"] /
9: ["nine", "九"] /
[数字, [英語, 漢数字]]の場合と同じでしたね。
結論
丸括弧を適切に使うことで、希望通りにブロックパラメータを取得できますね。
すごいぞRubyインタプリタ☆