Loop through and list a 2 column db table from Tinytds via ruby with column1 values as headings and column2 values as a list

StackOverflow https://stackoverflow.com/questions/16664736

  •  30-05-2022
  •  | 
  •  

Question

I've been trying to learn the basics of loops and I'm getting there but I'm struggling to get my brain around the following requirement where, for example, I've got data from a database table via tinytds, such that key/values are hashed into an array it seems(? - beginner here, so hope my terminology is correct!):-

The data is such that the values from one 'column' of the db table is repeated many times, whilst the values of the 2nd 'column' are unique.

Therefore, rather than simply creating a table in HTML for output that simply has 2 columns with column1 showing the same line of text over and over (before the next unique string lists over and over), I'd like to present the information so that unique string values from column1 are headings and the values of column2 are then listed beneath.

In my mind, I think what I'm trying to achieve is to loop through column1 for each unique string, output that value, whilst running an inner loop to list all values for column2 where column1 is 'string', moving on to the next unique value of column1,output that value, then loop through column2 again to list all values where column1 is 'string2' etc.

Hope that makes sense as I'm struggling to know how to explain in the correct terminology.

Thanks.

For example, if my 2 columns from my database table were as follows:-.

Column1
Q1
Q1
Q1
Q2
Q2
Q3
Q3
Q3

Column2
A1
A2
A3
A4
A5
A6
A7
A8

How could I loop (or whatever is best) through to be able to present the output such as:-

Q1
A1
A2
A3

Q2
A4
A5

Q3
A6
A7
A8

I can write the HTML side to format the output, I just can't figure out the ruby side.

For a single loop I've picked up from tiny_tds examples the following ruby (the html here is just to test placement for now):-

<% narrative.each do |question| %>
<span><%=question.values[1] %></span>
<br/>   
<% end %>

That allows me to list all the values for slot 2 (is that correct terminology?) and I could do something like:-

<% narrative.each do |question| %>
<span><%=question.values[0] %></span><span><%=question.values[1] %></span>
<br/>   
<% end %>

To show both side by side, but what I'm wanting to do is be more like:-

<h1>Question1 goes here</h1>
<ul>
<li>Answer 1</li>
<li>Answer 2</li>
<li>Answer 3</li>
</ul>
<h1>Question2 goes here</h1>
<ul>
<li>Answer 4</li>
<li>Answer 5</li>
</ul>

etc.

Was it helpful?

Solution

If you want to keep it simple, do it this way, just giving the logic, in stead of the puts add your html tags

a1 = [:Q1,:Q1,:Q1,:Q2,:Q2,:Q3,:Q3,:Q3] 
a2 = [:A1,:A2,:A3,:A4,:A5,:A6,:A7,:A8]

a3 = a1.zip a2
#=>[[:Q1, :A1], [:Q1, :A2], [:Q1, :A3], [:Q2, :A4], [:Q2, :A5], [:Q3, :A6], [:Q3, :A7], [:Q3, :A8]]

a3.each_with_index do |e, i|
  puts "#{e[0] if e[0] != a3[i-1][0]} #{e[1]}"
end

=>
Q1 A1
 A2
 A3
Q2 A4
 A5
Q3 A6
 A7
 A8

OTHER TIPS

Okay! I think below would help you to reach to your goal:

>> Column1 = [:Q1,:Q1,:Q1,:Q2,:Q2,:Q3,:Q3,:Q3] 
=> [:Q1, :Q1, :Q1, :Q2, :Q2, :Q3, :Q3, :Q3]
>> Column2 = [:A1,:A2,:A3,:A4,:A5,:A6,:A7,:A8]
=> [:A1, :A2, :A3, :A4, :A5, :A6, :A7, :A8]
>> h = Column1.each_with_object(Hash.new(0)){|i,ob| ob[i] = ob[i] + 1 }
=> {:Q1=>3, :Q2=>2, :Q3=>3}
>> enu = Column2.to_enum
=> #<Enumerator: [:A1, :A2, :A3, :A4, :A5, :A6, :A7, :A8]:each>
>> h1 = h.each_with_object(Hash.new([])){|(k,v),ob| v.times{ ob[k] = ob[k].dup.push(enu.next) } }
=> {:Q1=>[:A1, :A2, :A3], :Q2=>[:A4, :A5], :Q3=>[:A6, :A7, :A8]}
>> h1.each{|k,v| puts k,v}
Q1
A1
A2
A3
Q2
A4
A5
Q3
A6
A7
A8
=> {:Q1=>[:A1, :A2, :A3], :Q2=>[:A4, :A5], :Q3=>[:A6, :A7, :A8]}

Or you could do also as below:

a1 = [:Q1,:Q1,:Q1,:Q2,:Q2,:Q3,:Q3,:Q3] 
a2 = [:A1,:A2,:A3,:A4,:A5,:A6,:A7,:A8]

a3 = a1.zip(a2).group_by{|i| i[0]}
a3.each{|k,v| v.flatten!.delete(k); puts [k,v]}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top