2

次のコードがあり、正常に動作します。

months = {"Feb"=>["day1", "day2"]}

i = 0
while i < 5 do
   months["Feb"][i] = "day#{i}"
   i += 1
end
puts months

$> {"Feb"=>["day0", "day1", "day2", "day3", "day4"]}

しかし、ハッシュを初期化する最初の行を削除するか、その場で別のハッシュキーに値を追加しようとすると、「月」が未定義であるというエラーが発生します。

だから私は混乱しています。Ruby では、任意にキーをハッシュに追加することはできませんか? 私は、好きなようにハッシュと配列を作成し始めることができる Perl に慣れています。しかし、Perl はハッシュと配列を別のオブジェクトとして扱い、Ruby ではすべてが同じと見なされることを知っているので、それと関係があるかどうかはわかりませんでした (ただし、Perl のやり方はおそらく「ずさん」です ^_^ )

4

4 に答える 4

1

Rubyでは、変数を使用する前に変数を初期化する必要があります(健全なポリシーのように見えます...)。また、あなたが書いたものは慣用的なRubyではないことにも注意してください。

months = {"Feb" => 0.upto(4).map { |i| "day#{i}" }}

更新するには:

months["Feb"] = 0.upto(4).map { |i| "day#{i}" }
于 2012-10-13T11:32:13.010 に答える
1

Ruby では常に変数を初期化する必要があります。ただし、次のようにハッシュを初期化できます。

# Using {} to creates an empty hash
months = {}

# or create a new empty hash object from Hash class
months = Hash.new

# instead of
months = {"Feb"=>["day1", "day2"]}

ハッシュ内の配列を初期化するには:

# Array.new creates a new Array with size 5
# And values within Hash.new block are the default values for the hash
# i.e. When you call the Hash#[], it creates a new array of size 5
months = Hash.new { |hash, key| hash[key] = Array.new(5) }
puts months        #=> {}
puts months["Feb"] # Here the Hash creates a new Array inside "Feb" key
puts months        #=> {"Feb" => [nil, nil, nil, nil, nil]}
puts months["Feb"][3] = "Day3"
puts months        #=> {"Feb" => [nil, nil, nil, "Day3", nil]}

未定義の配列サイズを使用して同じことを行うには:

months = Hash.new { |hash, key| hash[key] = [] }
puts months        #=> {}
months["Feb"].push "Day0"
puts months        #=> {"Feb" => ["Day0"]}
months["Feb"].push "Day1"
puts months        #=> {"Feb" => ["Day0", "Day1"]}

よりエレガントなアプローチは、 map メソッドを使用して日の配列を作成してから、「Feb」キーにバインドすることだと思います。

months = {"Feb" => (0..4).map{ |i| "day#{i}" }}
# => {"Feb"=>["day0", "day1", "day2", "day3", "day4"]}

月の名前を入力したくない場合は、Date クラスを要求し、Fixnum を渡して月の名前を取得できます。

require 'date'
months = {Date::ABBR_MONTHNAMES[2] => (0..4).map{ |i| "day#{i}"}}
# => {"Feb"=>["day0", "day1", "day2", "day3", "day4"]}

すべての月に同じ構造を生成するには、次のようにします。

days   = (0..4).map{ |d| "day#{d}"}
months = (1..12).map{ |m| {Date::ABBR_MONTHNAMES[m] => days }}
# => {"Jan"=>["day0", "day1", "day2", "day3", "day4"],
#     "Feb"=>["day0", "day1", "day2", "day3", "day4"],
#     ...
#     "Dec"=>["day0", "day1", "day2", "day3", "day4"]}

いくつかの有用なドキュメント:

于 2012-10-13T14:55:13.543 に答える
0

あなたが言ったことに基づいて、私はいじりました.Rubyは、そのキーに値を割り当て始める前にキーが存在することを望んでいるようです.

hashname = Hash.new
hashname[:foo] = {}
hashname[:foo][3] = "test"
hashname[:foo][1] = "test1"
hashname[:bar] = {}
hashname[:bar][3] = "test3"
puts hashname
puts hashname[:foo][1]

C:\Ruby>scratch.rb
{:foo=>{3=>"test", 1=>"test1"}, :bar=>{3=>"test3"}}
test1

キーが存在すると、好きなように値の割り当てを開始できます。この場合、.map メソッドのように「配列のハッシュ」ではなく「ハッシュのハッシュ」を作成していることがわかりますが、その理由はまだわかりません。

助けてくれてありがとう!

于 2012-10-14T07:29:58.147 に答える
0
# the ||= set this to an empty hash({}) if it hasn't been initialized yet
months ||= {}

#updated as you like, use symbols :feb over string "feb" as the key (read this in other questions in this website)
months[:feb] = (0..4).map {|n| "day#{n}"}

p months  #==> {:feb=>["day0", "day1", "day2", "day3", "day4"]}
于 2012-10-13T14:35:50.690 に答える