0

初期化の違いに関するドキュメントはありますか?Hashのドキュメントには、違いを説明するものは何もありませんでした。

foo = [1,2,3,4]
test1 = Hash.new([])
test2 = Hash.new{|h,k| h[k] = []}

foo.each do |i| 
    test1[i] << i 
    test2[i] << i
end

puts "test 1: #{test1.size}" #0
puts "test 2: #{test2.size}" #4
4

3 に答える 3

3

ドキュメントに言及があります。ドキュメントを読む:

new(obj) → new_hash
new {|hash, key| block } → new_hash

[...] objが指定されている場合、この単一のオブジェクトがすべてのデフォルト値に使用されます。ブロックが指定されている場合、そのブロックはハッシュオブジェクトとキーを使用して呼び出され、デフォルト値を返す必要があります。必要に応じて値をハッシュに格納するのはブロックの責任です。

h = Hash.new("Go Fish")
h["a"] = 100
h["b"] = 200
h["a"]           #=> 100
h["c"]           #=> "Go Fish"
# The following alters the single default object
h["c"].upcase!   #=> "GO FISH"
h["d"]           #=> "GO FISH"
h.keys           #=> ["a", "b"]

# While this creates a new default object each time
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
h["c"]           #=> "Go Fish: c"
h["c"].upcase!   #=> "GO FISH: C"
h["d"]           #=> "Go Fish: d"
h.keys           #=> ["c", "d"]
于 2013-03-13T22:31:51.390 に答える
1

これはよくある落とし穴です。test1(非ブロック)を使用して、デフォルトのオブジェクトを変更します。これは、キーがハッシュに存在しない場合に取得するものです。

foo = [1,2,3,4]
test1 = Hash.new([])
test2 = Hash.new{|h,k| h[k] = []}

foo.each do |i| 
    test1[i] << i 
    test2[i] << i
    p test1['doesnotexist'] #added line
end

puts "test 1: #{test1.size}" #0
puts "test 2: #{test2.size}" #4

出力:

[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
test 1: 0
test 2: 4
于 2013-03-13T22:30:39.837 に答える
1

違いがあり、状況によっては重要になる可能性があります

test1 = Hash.new([])
test2 = Hash.new{|h,k| h[k] = []}

test1['foo'] #=> []
test2['foo'] #=> []

test1.keys == test2.keys #=> false

最初の構造はデフォルト値を返すだけですが、現在のハッシュでは何もしませんが、2番目の構造はキー/値でハッシュを初期化します。値は指定されたブロックによって計算されます。

于 2013-03-13T22:46:33.167 に答える