Estoy aprendiendo a codificar con ruby. Estoy aprendiendo sobre hashes y no entiendo este código: count = Hash.new(0) . Dice que el 0 es un valor predeterminado, pero cuando lo ejecuto en irb me da un hash vacío {}. Si 0 es un valor predeterminado, ¿por qué no puedo ver algo como count ={0=>0} ? ¿O el cero es un acumulador pero no va a las claves o valores? Gracias
0 será la alternativa si intenta acceder a una clave en el hash que no existe
Por ejemplo:
count = Hash.new -> count['key'] => nil
contra
count = Hash.new(0) -> count['key'] => 0
Para ampliar la respuesta de @jeremy-ramos y comentar de @mu-is-too-short.
Hay dos problemas comunes con valores hash predeterminados de esta manera.
Ruby usa exactamente el mismo objeto en la memoria que pasa como valor predeterminado para cada clave perdida.
Para un objeto inmutable (como 0 ), no hay problema. Sin embargo, es posible que desee escribir código como:
hash = Hash.new([]) hash[key] << valueo
hash = Hash.new({}) hash[key][second_key] = value Esto no hará lo que esperas. En lugar de hash[unknown_key] devuelva una nueva matriz vacía o hash, devolverá exactamente el mismo objeto de matriz/hash para cada clave.
así haciendo:
hash = Hash.new([]) hash[key1] << value1 hash[key2] << value2 da como resultado un hash donde key1 y key2 apuntan al mismo objeto de matriz que contiene [value1, value2]
Para resolver esto, puede crear un hash con un argumento de bloque predeterminado (que se llama cada vez que se accede a una clave faltante y le permite asignar un valor a la clave perdida)
hash = Hash.new{|h, key| h[key] = [] }Cuando accede a una clave faltante que devuelve el valor predeterminado, puede esperar que el hash ahora contenga esa clave con el valor devuelto. No es asi. Ruby no modifica el hash, simplemente devuelve el valor predeterminado. Así por ejemplo:
hash = Hash.new(0) #$> {} hash.keys.empty? #$> true hash[:foo] #$> 0 hash[:foo] == 0 #$> true hash #$> {} hash.keys.empty? #$> trueEsta confusión también se aborda mediante el enfoque de bloque, donde el valor de las claves se puede establecer explícitamente.
Los documentos Hash.new no son muy claros al respecto. Espero que el siguiente ejemplo aclare la diferencia y uno de los usos frecuentes de Hash.new(0) .
El primer fragmento de código usa Hash.new(0) . El hash tiene un valor predeterminado de 0, y cuando se encuentran claves nuevas, su valor es 0. Este método se puede usar para contar los caracteres en la matriz.
El segundo fragmento de código falla porque el valor predeterminado de la clave (cuando no está asignada) es nil . Este valor no se puede usar adicionalmente (al contar) y genera un error.
count = Hash.new(0) puts "count=#{count}" # count={} %w[abbccc].each do |char| count[char] += 1 end puts "count=#{count}" # count={"a"=>1, "b"=>2, "c"=>3} count = Hash.new puts "count=#{count}" %w[abbccc].each do |char| count[char] += 1 # Fails: in `block in <main>': undefined method `+' for nil:NilClass (NoMethodError) end puts "count=#{count}"VER TAMBIÉN: