Calculating Median in Ruby

跟風遠走 提交于 2019-12-03 04:11:29
nbarraille

Here is a solution that works on both even and odd length array and won't alter the array:

def median(array)
  sorted = array.sort
  len = sorted.length
  (sorted[(len - 1) / 2] + sorted[len / 2]) / 2.0
end

If by calculating Median you mean this

Then

a = [12,3,4,5,123,4,5,6,66]
a.sort!
elements = a.count
center =  elements/2
elements.even? ? (a[center] + a[center+1])/2 : a[center]  

Similar to nbarraille's, but I find it a bit easier to keep track of why this one works:

class Array
  def median
    sorted = self.sort
    half_len = (sorted.length / 2.0).ceil
    (sorted[half_len-1] + sorted[-half_len]) / 2.0
  end
end

half_len = number of elements up to and including (for array with odd number of items) middle of array.

Even simpler:

class Array
  def median
    sorted = self.sort
    mid = (sorted.length - 1) / 2.0
    (sorted[mid.floor] + sorted[mid.ceil]) / 2.0
  end
end
  def median(array)                          #Define your method accepting an array as an argument. 
      array = array.sort                     #sort the array from least to greatest
      if array.length.odd?                   #is the length of the array odd?
        array[(array.length - 1) / 2] #find value at this index
      else array.length.even?                #is the length of the array even?
       (array[array.length/2] + array[array.length/2 - 1])/2.to_f
                                             #average the values found at these two indexes and convert to float
      end
    end
def median(array)
  half = array.sort!.length / 2
  array.length.odd? ? array[half] : (array[half] + array[half - 1]) / 2 
end

*If the length is even, you must add the middle point plus the middle point - 1 to account for the index starting at 0

More correct solution with handling edge cases:

class Array
  def median
    sorted = self.sort
    size = sorted.size
    center = size / 2

    if size == 0
      nil
    elsif size.even?
      (sorted[center - 1] + sorted[center]) / 2.0
    else
      sorted[center]
    end
  end
end

There is a specs to prove:

describe Array do
  describe '#median' do
    subject { arr.median }

    context 'on empty array' do
      let(:arr) { [] }

      it { is_expected.to eq nil }
    end

    context 'on 1-element array' do
      let(:arr) { [5] }

      it { is_expected.to eq 5 }
    end

    context 'on 2-elements array' do
      let(:arr) { [1, 2] }

      it { is_expected.to eq 1.5 }
    end

    context 'on odd-size array' do
      let(:arr) { [100, 5, 2, 12, 1] }

      it { is_expected.to eq 5 }
    end

    context 'on even-size array' do
      let(:arr) { [7, 100, 5, 2, 12, 1] }

      it { is_expected.to eq 6 }
    end
  end
end
whatzzz

I think it's good:

#!/usr/bin/env ruby

#in-the-middle value when odd or
#first of second half when even.
def median(ary)
  middle = ary.size/2
  sorted = ary.sort_by{ |a| a }
  sorted[middle]
end

or

#in-the-middle value when odd or
#average of 2 middle when even.
def median(ary)
  middle = ary.size/2
  sorted = ary.sort_by{ |a| a }
  ary.size.odd? ? sorted[middle] : (sorted[middle]+sorted[middle-1])/2.0
end

I used sort_by rather than sort because it's faster: Sorting an array in descending order in Ruby.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!