21 - Hash: recorrido mediante los métodos each e each_value

En Ruby tanto con Array como con estructuras de tipo Hash se utilizan métodos y el concepto de bloques para recorrer.

El método más común para iterar un Hash en Ruby se llama each y tiene dos sintaxis para implementarlo.

Veamos las sintaxis para recorrer un Hash:

  • paises = {"argentina" => 40000000,
              "españa" => 46000000,
              "brasil" => 190000000,
              "uruguay" => 3400000}
    
    paises.each do |clave, valor|
      puts "#{clave} #{valor}"
    end
    

    Estamos llamando al método each y le pasamos un bloque encerrado entre las palabras claves do y end.

    El bloque tiene acceso en cada iteración o repetición a la clave y el valor del Hash indicada entre los símbolos |variable1, variable2|

    Si ejecutamos este programa vemos que aparecen todas las claves y sus valores asociados:

    argentina 40000000
    españa 46000000
    brasil 190000000
    uruguay 3400000
    
  • Cuando el algoritmo del bloque es muy reducido es común utilizar los símbolos {} en remplazo de las palabras claves do y end.

    paises = {"argentina" => 40000000,
              "españa" => 46000000,
              "brasil" => 190000000,
              "uruguay" => 3400000}
    
    paises.each {|clave, valor| puts "#{clave} #{valor}"}
    

    Normalmente los bloques de llaves se utilizan en una sola línea.

Problema 1:

Definir un Hash que almacene los nombres de paises como clave y como valor la cantidad de habitantes. Sumar la cantidad de habitantes de todos los paises.

Programa: ejercicio089.rb

paises = {"argentina" => 40000000,
          "españa" => 46000000,
          "brasil" => 190000000,
          "uruguay" => 3400000}

suma = 0
paises.each {|clave, valor| suma = suma + valor}

puts "La cantidad total de habitantes de todos los paises es #{suma}"

Previo a llamar al método each inicializamos el acumulador suma con cero. Luego dentro del bloque que le pasamos a each acumulamos todos los habitantes de cada país:

suma = 0
paises.each {|clave, valor| suma = suma + valor}

puts "La cantidad total de habitantes de todos los paises es #{suma}"

Es bueno siempre tener a mano la página oficial de la clase Hash de Ruby

Si buscamos entre la gran cantidad de métodos de la clase Hash podemos encontrar uno que se llama each_value que es similar a each salvo que no tenemos acceso a la clave. En este problema como solo debemos sumar todos los valores que se almacenan en el Hash es más conveniente el método each_value:

paises.each_value {|valor| suma = suma + valor}

Problema 2:

Desarrollar una aplicación que nos permita crear un diccionario ingles/castellano (utilizar un Hash). La clave es la palabra en ingles y el valor es la palabra en castellano.

Mostrar por pantalla cada palabra y su traducción separada por el caracter =

Programa: ejercicio090.rb

diccionario = {"red" => "rojo",
               "blue" => "azul",
               "yellow" => "amarillo",
               "green" => "verde"}

diccionario.each{|clave, valor| puts "#{clave}=#{valor}"}

En este problema es obligatorio utilizar el each ya que debemos acceder tanto a la clave como el valor del Hash:

diccionario.each{|clave, valor| puts "#{clave}=#{valor}"}

Problemas propuestos

  • Crear un Hash donde se almacene como clave el nombre de producto y como valor el precio del mismo.
    Imprimir solo los productos que tienen un precio mayor a 20 y al final indicar la cantidad de productos con dicha situación.
  • Crear un Hash que permita almacenar nombres de empleados de una empresa y su sueldo, utilizar como clave el nombre del empleado y como valor el sueldo del mismo.
    1) Cargar por teclado los empleados y sus sueldos.
    2) Mostrar la cantidad de empleados que tienen un sueldo mayor o igual a 1000 y cuantos menores a 1000.
Solución
ejercicio091.rb

productos = {"manzanas" => 25,
             "peras" => 32,
             "naranjas" => 15,
             "kiwis" => 56}
cantidad = 0
productos.each do |clave,valor|
  if valor > 20
    cantidad = cantidad + 1
    puts clave
  end
end
puts "La cantidad de productos con un precio mayor a 20 son #{cantidad}"




ejercicio092.rb

empleados = {}

loop do
  print "Ingrese el nombre del empleado:"
  nom = gets.chomp
  print "Ingrese el sueldo:"
  sueldo = gets.to_f
  empleados[nom] = sueldo
  print "¿Desea ingresar otro empleado [s/n]?"
  opcion = gets.chomp
  if opcion == "n"
    break
  end
end

altos = 0
bajos = 0
empleados.each_value do |valor|
  if valor >= 1000
    altos = altos + 1
  else
    bajos = bajos + 1
  end
end

puts "La cantidad de empleados con sueldos mayores o igual a 1000 son #{altos}"
puts "La cantidad de empleados con sueldos menores a 1000 son #{bajos}"