Ruby:如何添加到数组的新哈希?

Ruby:如何添加到数组的新哈希?,ruby,arrays,hash,Ruby,Arrays,Hash,我有下面的代码,它工作得很好 months = {"Feb"=>["day1", "day2"]} i = 0 while i < 5 do months["Feb"][i] = "day#{i}" i += 1 end puts months months={“Feb”=>[“day1”,“day2”]} i=0 而我不到5岁 月[“二月”][i]=“日{i}” i+=1 结束 放个月 $>{“二月”=>[“第0天”、“第1天”、“第2天”、“第3天”、“第4天”

我有下面的代码,它工作得很好

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

i = 0
while i < 5 do
   months["Feb"][i] = "day#{i}"
   i += 1
end
puts months
months={“Feb”=>[“day1”,“day2”]}
i=0
而我不到5岁
月[“二月”][i]=“日{i}”
i+=1
结束
放个月
$>{“二月”=>[“第0天”、“第1天”、“第2天”、“第3天”、“第4天”]]

但是,如果我删除初始化散列的第一行,或者尝试动态地向不同的散列键添加值,我会得到一个错误,在undefined中为“months”


所以我很困惑。Ruby不允许您向散列任意添加键吗?我已经习惯了Perl,在Perl中,您可以随意创建散列和数组。但是我知道Perl将哈希和数组视为单独的对象,而Ruby则认为所有内容都是相同的,所以我不知道这是否与此有关(尽管Perl的方式可能是“草率的”^ ^)

在Ruby中,在使用变量之前必须先初始化它(看起来像一个合理的策略…)。还要注意的是,您编写的不是惯用Ruby,而是一种替代方法:

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

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

您总是需要在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”键之前构建天数数组:

如果不想键入月份名称,可以要求使用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"]}
一些有用的文档:


根据你们所说的,我搞砸了,看起来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方法那样创建一个“数组哈希”,但我仍然不知道为什么


谢谢你的帮助

您可以动态添加键和值,但必须初始化第一个空数组。例如,仅使用日历字。.map方法确实有效,但是如果我只想在数组的散列中插入一个元素呢?我不想进行计数,我只想在hashname[key][2]中插入一个值。Ruby的抱怨似乎是希望钥匙存在。添加数组元素似乎没有任何问题,但如果键不存在,它就会抱怨。有没有一种简单的方法可以在散列中创建一个键,然后从那里开始填充?我改进了我的答案,希望它能帮助您。
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"]}
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