1

This is my first S.O. question so please be kind.

I have an array of year/month values that looks something like this

[["2012", "1"], ["2013", "3"], ["2013","4"], ["2013", "3"]]

Essentially I have a rails active record that when i am looping through my array if the year and month already exist I dont want to create a new row I want to put the data in one of my 4 columns in a previous existing row.

So the table might look like this

<table>
   <tr>
      <th>Month/Year</th>
      <th>Sales</th>
      <th>Tech Support</th>
      <th>Management</th>
   </tr>
   <tr>
      <td>Jan/12</td>
      <td>10</td>
      <td>%nbsp;</td>
      <td>&nbsp;</td>
   </tr>
   <tr>
      <td>Mar/13</td>
      <td>&nbsp;</td>
      <td>10</td>
      <td>&nbsp;</td>
   </tr>
   <tr>
      <td>Apr/13</td>
      <td>&nbsp</td>
      <td>%nbsp;</td>
      <td>10;</td>
   </tr>
   <tr>
      <td>Mar/13</td>
      <td>10</td>
      <td>%nbsp;</td>
      <td>&nbsp;</td>
   </tr>
</table>

I have if statements that tell me if it's Sales, Tech Support, or Managment so that it knows which column to put it in, my issue.

Essentially what I want is that last row of Mar/13 to say "hey you already have a Mar/13 row, this value should go into one of it's columns (and the data is such that I will never repeat a column.)

Would I be better served by creating the table with ID's for the TD's in rails that match the year/month/column and then assigning the active record to a javascript array that uses those IDs to put the values in using the innerHTML or is there a smarter way to do this?

3
  • Essentially what I want is that last row of Mar/13 to say "hey you already have a Mar/13 row, this value should go into one of it's columns (and the data is such that I will never repeat a column.) do you mean should go into one of it's existing rows? Commented Sep 1, 2017 at 18:00
  • Yes. So some data may be something like Management, March/13, 5 then another piece may be Sales, March/13, 10. Essentially when I get the same Month and Year combo I want to put that piece of data in the row for that month/year but the category will always be only one of 3 (Sales, Tech Support, or Management) it will never have the same month/year and category but the month and year combo could potentially be the same, but not month/year/category. Commented Sep 1, 2017 at 22:26
  • So I may have something like {year:2012, month:3, category:sales, total:3} {year:2013, month:3, category:management, total:3} {year:2013, month:1, category:tech support, total:5} {year:2013, month:3, category:tech support, total:3} So when making the table my March 2013 will only have one row but 2 of the 3 columns filled out. Commented Sep 1, 2017 at 22:30

1 Answer 1

1

I would recommend grouping the data before trying to output any of it in the view, using the data you gave in the comment, we can do something like:

data = [
  { name: 'John', year: 2012, month: 3, category: 'sales', total: 3 },
  { name: 'Jacob', year: 2013, month: 3, category: 'management', total: 3 },
  { name: 'Jingleheimer', year: 2013, month: 1, category: 'tech support', total: 5 },
  { name: 'Schmidt', year: 2013, month: 3, category: 'tech support', total: 3 }
]

grouped = data.group_by { |datum| [datum[:year], datum[:month]] }

# Ruby 2.4+
transformed = grouped.transform_values do |values|
  values.each.with_object({}) do |value, result|
    result.merge!("#{value[:category]} Name" => value[:name],
                  value[:category] => value[:total])
  end
end

puts transformed.inspect
# => {[2012, 3]=>{"sales Name"=>"John", "sales"=>3},
#     [2013, 3]=>{"management Name"=>"Jacob", "management"=>3,
#                 "tech support Name"=>"Schmidt", "tech support"=>3},
#     [2013, 1]=>{"tech support Name"=>"Jingleheimer", "tech support"=>5}}

# Ruby < 2.4
transformed = grouped.map do |year_month, values|
  [year_month, values.each.with_object({}) do |value, result|
    result.merge!("#{value[:category]} Name" => value[:name],
                  value[:category] => value[:total])
  end]
end.to_h


puts transformed.inspect
# => {[2012, 3]=>{"sales Name"=>"John", "sales"=>3},
#     [2013, 3]=>{"management Name"=>"Jacob", "management"=>3,
#                 "tech support Name"=>"Schmidt", "tech support"=>3},
#     [2013, 1]=>{"tech support Name"=>"Jingleheimer", "tech support"=>5}}

Then you can just iterate that new hash with the [year, month] array as the keys and the values being a hash of category => total_for_category and output them however you'd like.

Sign up to request clarification or add additional context in comments.

4 Comments

I'm in training all this week, Ill try this once i get back and give you an upvote if i get it working. Thanks.
So I almost have this working but I had forgot one more thing, my data also has a name attached to each item which I need in my transform as well (I'm using your 2.4) So a piece of data may look like {name:'Jamie', year: 2013, month: 3, category: 'tech support', total: 3 } When I try to add it on the values.map I get an error of "wrong array length, expected 2, was 3" The data looks like something I can work with, I just need name too. Without the name it looks something like [[["2012", "3"], {"Tech Support"=>"3""}], ["2012","1"],{"Tech Support"=>"5"}]] How can I add name?
@Jamie updated my answer with a more extensible solution
Bingo. That gives me some stuff I can work with to put into an HTML table. You get the upvote.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.