Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

390
Views
How to combine and print values of nested object structure?

I have an array of hashes and each hash needs to be printed out on the same line.

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 }] }
]

I want it to be looked like this:

Card 6: 1 head / Card 10: 1 head
Card 53: 1 head / Card 60: 1 head
Card 77: 5 head
Card 89: 1 haed

I tried below:

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
end

Which outputs the data as:

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. / 

I am sorry that my array is so nested as I need to sort the order by num for each hash, I put them in an array.

Thanks in advance!

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

You can iterate the hashes in init_cards_j via each and for each hash call each_value to traverse its values. Then, instead of printing every card right away, you can generate an intermediate array via map and join the result using your separator string:

init_cards_j.each do |hash|
  hash.each_value do |values|
    puts values.map { |c| "Card #{c[:num]}: #{c[:head]} head" }.join(' / ')
  end
end

But it would be easier to convert the array of hashes to a single hash: (assuming that their keys are unique)

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 }]
}

If you must retain the given structure, you could convert it on the fly:

cards = init_cards_j.inject(&:merge)

This makes the loop a bit simpler:

cards.each_value do |values|
  puts values.map { |c| "Card #{c[:num]}: #{c[:head]} head" }.join(' / ')
end

To further refine the output, you can separate the looping from the card description by extracting the latter into a method:

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

You can now adding more logic to the output string by editing the description method, e.g.:

def description(card)
  if card[:head] == 1
    "Card #{card[:num]}: #{card[:head]} head"
  else
    "Card #{card[:num]}: #{card[:head]} heads"
  end
end

The above can be written much more compact, but I'll leave the optimization to you.

over 4 years ago · Santiago Trujillo Report

0

I would recommend @Stefan's first answer, but here is another way to achieve the same result.

We might begin with a helper method, which of course you can test separately:

def print_num_and_head(g)
  print "Card %d: %d head" % g.values_at(:num, :head)
end

If

g = {:num=>6, :head=>1})

then

print_num_and_head(g)

displays

Card 6: 1 head

without a line terminator.

We may then write:

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   
end

prints

Card 6: 1 head / Card 10: 1 head
Card 53: 1 head / Card 60: 1 head
Card 77: 5 head
Card 89: 1 head

Here I've used Ruby's powerful array#decomposition (a.k.a array disambiguation) syntax to advantage:

If

h = { init1: [{ num: 6, head: 1 }, { num: 10, head: 1 }] }

then

_, (g, *arr) = h.flatten
  #=> [:init1, [{:num=>6, :head=>1}, {:num=>10, :head=>1}]]
_ #=> :init1
g #=> {:num=>6, :head=>1}
arr
  #=> [{:num=>10, :head=>1}]

I've employed the common convention of representing a block variable with an underscore when it is not used in the block calculation.

See this article for a fuller explanation array decomposition.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!