16
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

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

ふと気付いた

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

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
16
Help us understand the problem. What are the problem?