LoginSignup
18
16

More than 5 years have passed since last update.

eachメソッドでブロックパラメータを複数取れる場合

Last updated at Posted at 2014-05-12

ふと気付いた

先日こういう記事を書きました。
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インタプリタ☆

18
16
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
18
16