views:

370

answers:

4

Hi

I have searched/Googled around but I'm struggling with the following problem.

I am building a Rails 2.3.2 application and one of the requirements is to calculate the median of an array of results. I am using code for calculating the median from the Ruby Cookbook but keep running in to a problem with receiving an error 'LocalJumpError - no block given' when I attempt to find the median of an array where there are an odd number of members.

The example code in my view is as follows:

<%= survey_response.median([6,4,5,4,4,2]) %>

Then in survey_response.rb model the methods are as follows:

def mean(array)
  array.inject(array.inject(0) { |sum, x| sum += x } / array.size.to_f)
end

def median(array,already_sorted=false)
  return nil if array.empty?
  array = array.sort unless already_sorted
  m_pos = array.size / 2
  return array.size % 2 == 1 ? array[m_pos] : mean(array[m_pos-1..m_pos])      
end

The error is caused when the median method refers back to the mean method to get the media of an odd total of items in the array. I just can't figure out why I get that error or indeed how to fix it - so I'd hugely appreciate any help/guidance/laughing anybody could offer me!

Thanks

Simon

+1  A: 

Lis looks like it's due to you using a fractional index into the array. Try replacing:

m_pos = array.size / 2

with:

m_pos = (array.size / 2).ceil

Also, try changing your mean function to this:

def mean(array)
  array.inject(0) { |sum, x| sum += x } / array.size.to_f
end
Mr. Matt
Hey thanks for replying - unfortunately that make's no difference. I still get the same error when there are an odd number of items in the array. Is there any other information I can provide which might be useful?
Thanks - with the edit to the mean() function this also works a treat.
+1  A: 

Better code:

def mean(array)
  array.inject { |sum, n| sum + n } / array.length.to_f
end

def median(array)
  return nil if array.empty?
  array.sort!
  middle = array.length / 2
  (array.length % 2 == 1) ? array[middle] : mean([array[middle-1], array[middle]])
end

puts median([5,11,12,4,8,21]) # => 9.5
HeyI added: numbers = numbers.sortbecause the array needs sorting before you find the median but it's definitely fixed my problem otherwise. Thanks a lot!
+1  A: 

That mean method looks horribly botched. Try this:

def mean(array)
  a.inject(0) { |sum,x| sum += x } / a.size.to_f
end
Hemant Kumar
Thanks - replacing the mean() method with your alternative also fixed the problem and gives me a mean() method for use elsewhere too.
Ha ha. Its probably nothing but Mr.Matt edited his post good 20 minutes after I pointed actual error in original code and copied my correction of `mean` method in his edit.
Hemant Kumar
Except that I made that change 4 minutes before you posted your answer.
Mr. Matt
Hmm, odd my mistake. I didn't see your edit the time I submitted my response, but anyways my apologies.
Hemant Kumar
A: 

This is the solution for my error i am searching. Thank you so much.