【问题标题】:Calculating Median in Ruby在 Ruby 中计算中位数
【发布时间】:2013-01-29 07:52:00
【问题描述】:

如何使用 Ruby 计算数字数组的中位数?

我是一个初学者,正在努力处理数组长度为奇数和偶数的情况。

【问题讨论】:

标签: ruby median


【解决方案1】:

我喜欢使用 Refinements,这是一种Monkey Patch ruby​​ 类的安全方法,不会对系统产生附带影响。

用法变得比新方法更简洁。

使用Refinements,您可以修改Array 类,实现Array#median,此方法仅在使用细化的类范围内可用! :)

改进

module ArrayRefinements
  refine Array do
    def median
      return nil if empty?
      sorted = sort
      (sorted[(length - 1) / 2] + sorted[length / 2]) / 2.0
    end
  end
end

class MyClass
  using ArrayRefinements
  # You can use the Array#median as you wish here

  def test(array)
    array.median
  end
end

MyClass.new.test([1, 2, 2, 2, 3])
=> 2.0

【讨论】:

    【解决方案2】:

    这是一个适用于偶数和奇数长度数组且不会改变数组的解决方案:

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

    【讨论】:

    • return 0 if array.empty?
    • @ArtemKalinchuk 为什么是 0?空数组的中位数未定义。我同意应该改进此方法以通过返回 Float::NAN 之类的内容或引发自定义的更明确的错误来处理这种情况。
    【解决方案3】:
    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
    

    【讨论】:

      【解决方案4】:

      这里有一个解决方案:

      app_arry = [2, 3, 4, 2, 5, 6, 16].sort
      
      # check array isn't empty
      if app_arry.empty?  || app_arry == ""
        puts "Sorry, This will not work."
        return nil
      end
      
      length = app_arry.length
      puts "Array length = #{length}"
      puts "Array = #{app_arry}"
      
      if length % 2  == 0
       # even number of elements
       puts "median is #{(app_arry[length/2].to_f +  app_arry[(length-1)/2].to_f)/2}"
      else
       # odd number of elements
       puts "median is #{app_arry[(length-1)/2]}"
      end
      

      输出

      数组长度 = 7

      数组 = [2, 3, 4, 2, 5, 6, 16]

      中位数是 2

      【讨论】:

        【解决方案5】:
        def median(arr)
            sorted = arr.sort 
            if sorted == []
               return nil
            end  
        
            if sorted.length % 2 != 0
               result = sorted.length / 2 # 7/2 = 3.5 (rounded to 3)
               return sorted[result] # 6 
            end
        
            if sorted.length % 2 == 0
               result = (sorted.length / 2) - 1
               return (sorted[result] + sorted[result+1]) / 2.0 #  (4 + 5) / 2
            end
        end
        
        p median([5, 0, 2, 6, 11, 10, 9])
        

        【讨论】:

          【解决方案6】:
            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
          

          【讨论】:

          • 有很多方法可以做到这一点,但你的答案是最优雅的。很清楚发生了什么。
          • 如果array.length不是奇数,那么是偶数,还是别的什么?,else后面的表达式是不是必须的,return也需要吗?
          • 我认为也不需要均匀评估。
          【解决方案7】:

          处理边缘情况的更正确解决方案:

          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
          

          有一个规格要证明:

          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
          

          【讨论】:

            【解决方案8】:
            def median(array)
              half = array.sort!.length / 2
              array.length.odd? ? array[half] : (array[half] + array[half - 1]) / 2 
            end
            

            *如果长度是偶数,则必须加上中间点加上中间点-1来说明从0开始的索引

            【讨论】:

            • 使用array.sort! 不是一个好主意,因为它会改变参数
            【解决方案9】:

            类似于 nbarraille,但我发现跟踪它的工作原理更容易一些:

            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 = 直到并包括(对于奇数项的数组)数组中间的元素数。

            更简单:

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

            【讨论】:

              【解决方案10】:

              我觉得不错:

              #!/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
              

              #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
              

              我使用 sort_by 而不是 sort,因为它更快:Sorting an array in descending order in Ruby

              【讨论】:

                【解决方案11】:

                如果计算中位数是指this

                然后

                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]  
                

                【讨论】:

                • 是的,第一个偶数使它成为一个 if ... else 过程(到目前为止我所学到的)
                • 不一定要有if/else,看我的回答
                • 需要2.0to_f 才能使4.5 之类的结果成为可能。
                • 另外最后一行应该是elements.even? ? (a[center] + a[center-1])/2.0 : a[center](注意a[center-1]2.0中的减号)否则偶数长度数组的中值会偏移数组中的1个索引位置.尝试使用 2 值数组的原始代码,你会得到一个错误。这只是咬我...
                猜你喜欢
                • 1970-01-01
                • 2011-05-15
                • 1970-01-01
                • 2011-05-07
                • 2018-01-24
                • 2011-06-14
                • 2011-12-05
                • 2021-08-17
                相关资源
                最近更新 更多