1

Please explain this Ruby code so I can convert it to PHP:

data = Hash.new({})
mysql_results.each { |r| data[r['year']][r['week']] = r['count'] }

(year_low..year_high).each do |year|
  (1..52).each do |week|
   puts "#{year} #{week} #{data[year][week]}"
  end
end
6
  • 3
    There's a bug here: data hash won't be updated by the second line because it in fact changes the default hash value. Commented May 12, 2010 at 14:22
  • @Mladen, comment++. It is a damning bug. It will appear to work if the range of years is a single year, or if the weeks in (year, week) tuples don't overlap, because access will return the same mutated default hash. The original coder may never have known -- s/he certainly doesn't call data.keys(), which would be empty, even though data[year] returns something meaningful... Commented May 12, 2010 at 14:33
  • @Mladen: very correct. Default hash values can lead to funky bugs. Sorry to put this all on one line, but this is probably a better strategy (if my guess about the desired behavior is correct): h = {}; [[2010, 5, 3], [2010,6,27]].each { |r| h[r[0]] = {} if !h.has_key?(r[0]); h[r[0]][r[1]] = r[2] } Commented May 12, 2010 at 14:37
  • @Benjamin, simpler formulation: data = Hash.new { |me, key| me[key] = {} }. Commented May 12, 2010 at 14:41
  • @pilcrow: Nice. I tried to do something like that at first, but just decided on the has_key? route. Updated: h = Hash.new { |me, key| me[key] = {} }; [[2010, 5, 3], [2010,6,27]].each { |r| h[r[0]][r[1]] = r[2] }. Commented May 12, 2010 at 15:04

3 Answers 3

6
data = Hash.new({})
# create hash 'data'
mysql_results.each { |r| data[r['year']][r['week']] = r['count'] }
# maps each row from sql query to hash like this: data[2010][30] = 23
# So you can access 'count' from every year and week in very simple way

(year_low..year_high).each do |year|
# for (year = year_low; year <= year_high; year++) 
  (1..52).each do |week|
  # for (week = 1; week <=52; week++)
   puts "#{year} #{week} #{data[year][week]}"
   # printf("%d %d %d\n", year, week, data[year][week]);
  end
end

Sorry for mixing C with pseudo code, but I hope it helps!

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

1 Comment

Second line in php does this: foreach($mysql_results as $row) { $data[$row['year']][$row['week']] = $row['count']; }
1

The first bit is just forming an array like so:

$data[2009][17] = 10;

PHP equivalent of that would be:

foreach ($mysql_results as $r){
  $data[$r['year']][$r['week']] = $r['count'];
}

The second part would equate to the following:

foreach(range($year_low, $year_high) as $year){
  foreach(range(1, 52) as $week){
    print $year.' '.$week.' '.$data[$year][$week]
  }
}

Hope that helps :)

1 Comment

+1 for remembering the range() function. I always forget, and resort to a simple for() instead..
0
$data = array();

#Build an array of 'count' per year/week
foreach($mysql_results as $r) {
    $data[$r['year']][$r['week']] = $r['count'];
}

#Loop through the $data variable, printing out the 'count' for each year in the array,
#and all 52 weeks that year
for($year = $year_min; $year <= $year_max; $year++) {
    for($week=1; $week<=52; $week++) {
        echo "$year $week {$data[$year][$week]}";
    }
}

Note that year_low and year_high are variables undefined in the current snippet, but they should be known to you.

Also, $mysql_results should be an array containing all rows returned by the database.

In short, the following code does this:

  • Make an array grouped per year, then per week, containing the value 'count'
  • Loop through this array, displaying, in order, the year, the week, and the value for 'count', if any

Comments

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.