Tengo una matriz de hash y cada hash debe imprimirse en la misma línea.
init_cards_j = [ { init1: [{ num: 6, head: 1 }, { num: 10, head: 1 }] }, { init2: [{ num: 53, head: 1 }, { num: 60, head: 1 }] }, { init3: [{ num: 77, head: 5 }] }, { init4: [{ num: 89, head: 1 }] } ]Quiero que se vea así:
Card 6: 1 head / Card 10: 1 head Card 53: 1 head / Card 60: 1 head Card 77: 5 head Card 89: 1 haedProbé a continuación:
init_cards_j.each_index do |index| init_cards_j[index].values[0].each do |pair| init_cards_j[index].each do |key, value| value.each do |pair| puts "Card #{pair[:num]}: #{pair[:head]} kettle head. / " end end end endQue genera los datos como:
Card 6: 1 kettle head. / Card 10: 1 kettle head. / Card 6: 1 kettle head. / Card 10: 1 kettle head. / Card 53: 1 kettle head. / Card 60: 1 kettle head. / Card 53: 1 kettle head. / Card 60: 1 kettle head. / Card 77: 5 kettle head. / Card 89: 1 kettle head. / Lamento que mi matriz esté tan anidada que necesito ordenar el orden por num para cada hash, los puse en una matriz.
¡Gracias por adelantado!
Puede iterar los hashes en init_cards_j a través de each y para cada hash llame a each_value para recorrer sus valores. Luego, en lugar de imprimir todas las tarjetas de inmediato, puede generar una matriz intermedia a través del map y join el resultado usando su cadena de separación:
init_cards_j.each do |hash| hash.each_value do |values| puts values.map { |c| "Card #{c[:num]}: #{c[:head]} head" }.join(' / ') end endPero sería más fácil convertir la matriz de hash en un solo hash: (suponiendo que sus claves sean únicas)
cards = { init1: [{ num: 6, head: 1 }, { num: 10, head: 1 }], init2: [{ num: 53, head: 1 }, { num: 60, head: 1 }], init3: [{ num: 77, head: 5 }], init4: [{ num: 89, head: 1 }] }Si debe conservar la estructura dada, puede convertirla sobre la marcha:
cards = init_cards_j.inject(&:merge)Esto hace que el ciclo sea un poco más simple:
cards.each_value do |values| puts values.map { |c| "Card #{c[:num]}: #{c[:head]} head" }.join(' / ') endPara refinar aún más la salida, puede separar el bucle de la descripción de la tarjeta extrayendo esta última en un método:
def description(card) "Card #{card[:num]}: #{card[:head]} head" end init_cards_j.each do |hash| hash.each_value do |values| puts values.map { |card| description(card) }.join(' / ') end end Ahora puede agregar más lógica a la cadena de salida editando el método de description , por ejemplo:
def description(card) if card[:head] == 1 "Card #{card[:num]}: #{card[:head]} head" else "Card #{card[:num]}: #{card[:head]} heads" end endLo anterior se puede escribir mucho más compacto, pero te dejaré la optimización a ti.
Recomendaría la primera respuesta de @Stefan, pero aquí hay otra forma de lograr el mismo resultado.
Podríamos comenzar con un método de ayuda, que por supuesto puede probar por separado:
def print_num_and_head(g) print "Card %d: %d head" % g.values_at(:num, :head) endSi
g = {:num=>6, :head=>1})entonces
print_num_and_head(g)muestra
Card 6: 1 headsin un terminador de línea.
Entonces podemos escribir:
init_cards_j.each do |h| _, (g, *arr) = h.flatten print_num_and_head(g) arr.each do |g| print ' / ' print_num_and_head(g) end puts endhuellas dactilares
Card 6: 1 head / Card 10: 1 head Card 53: 1 head / Card 60: 1 head Card 77: 5 head Card 89: 1 headAquí he usado la potente sintaxis de matriz # descomposición (también conocida como desambiguación de matriz ) de Ruby para sacar ventaja:
Si
h = { init1: [{ num: 6, head: 1 }, { num: 10, head: 1 }] }entonces
_, (g, *arr) = h.flatten #=> [:init1, [{:num=>6, :head=>1}, {:num=>10, :head=>1}]] _ #=> :init1 g #=> {:num=>6, :head=>1} arr #=> [{:num=>10, :head=>1}]He empleado la convención común de representar una variable de bloque con un guión bajo cuando no se usa en el cálculo del bloque.
Consulte este artículo para obtener una explicación más completa de la descomposición de matrices.