【问题标题】:Find the median of an array查找数组的中位数
【发布时间】:2014-02-24 13:43:03
【问题描述】:

我编写了一些代码,它返回未排序的奇数数组的中值,但它不返回偶数数组的中值。

我知道为了找到偶数数组的中位数,你必须取数组的中间两个数,平均它们,这就是中位数。我无法将其翻译成可用的代码。除了这段代码明显冗长之外,问题似乎出在第 7-8 行,我不明白为什么。

我更喜欢提示而不是答案,但如果你更愿意发布一些固定的代码,我也可以接受。

def media(array)
  sorted = array.sort
  list = sorted.length
  if list %2 != 0
    (list + 1) / 2.0
  else
    even = ((list.to_f + 2) / 2) + ((list.to_f / 2)
    return (even/2)
  end
end

【问题讨论】:

  • jr,需要对sorted的元素进行操作,而不是对它的长度进行操作。请注意,排序现在对您没有任何作用; list = array.length 会产生相同的结果。您需要使用sorted
  • 对于奇数长度,您将返回中位数 index。对于偶数长度,没有可以返回的索引,对吗?因此重写它,以便它返回计算值。例如。对于奇数数组,返回sorted[(list+1)/2],对于偶数数组,返回(sorted[i]+sorted[i-1])/2,您需要计算i
  • 您是要查找数组中的中位数value,还是排序后数组中位数的index?因为您的代码似乎正在尝试执行后者。
  • 请记住,ruby 数组索引从零开始,因此当长度为奇数时,感兴趣的索引为 array.length / 2,如果长度为偶数,则为 array.length / 2(array.length / 2) - 1
  • 感谢这些有用。立即再次卡住 - 我不知道第二个答案中的代码发生了什么:'sorted[(list+1)/2]' and '(sorted[i]+sorted[i-1])/2 '。是否应该读作“排序时间列表 + 1,除以 2”和“排序时间 i + 排序时间 (i -1),然后除以 2”?

标签: ruby arrays median


【解决方案1】:

我将在这里提出一个解决方案...

def median(ary)
  mid = ary.length / 2
  sorted = ary.sort
  ary.length.odd? ? sorted[mid] : 0.5 * (sorted[mid] + sorted[mid - 1])
end

编辑 - 根据 BroiSatse 的建议,我已合并 .odd?

【讨论】:

  • 使用& 1 真的很奇怪。最好是@BroiSatse 推荐的% 2 == 0.odd?
  • @tadman 我想我在暴露我的年龄。早在过去,我们就曾尝试尽可能避免基于部门的操作,其中包括 %
  • 也许将 ? sorted[mid] : 更改为 ? sorted[mid].to_f : 以便它始终返回一个浮点数。
  • @CarySwoveland 当 n 为奇数时,中位数是实际值之一,但当 n 为偶数时,中位数是两个值的平均值。在第二种情况下返回浮点数是正确的做法,但在第一种情况下,我认为最好按原样返回值。
  • @CarySwoveland 我更喜欢坚持统计定义,它说中位数是两个事物之一,一个原始值或两个值的平均值,这取决于集合的基数是偶数还是偶数奇怪的。如果有人想在后续操作中使用中间值,则由他们来确保他们以与他们想要执行的操作一致的方式使用它。
【解决方案2】:
  a = [1,2,4,5,3,6]
  sorted = a.sort
  list = sorted.length
  if list %2 != 0
    puts sorted[list/2]
  else
    puts (sorted[list/2]+sorted[(list/2)-1])/2.0
  end

【讨论】:

    【解决方案3】:
    def get_median(values)
      quotient, remainder = values.sort!.length.divmod(2)
      medians = [values[quotient], values[quotient-(remainder+1) % 2]].uniq
      medians.length > 1 ? medians.map(&:to_f).reduce(:+) / 2 : medians[0]
    end
    

    应该有效,但如果无效,请告诉我。

    edit 忘记将 .to_f 添加到中值。这是我在 Pry 中的测试。

    [1] pry(main)> def get_median(values)
    [1] pry(main)*   quotient, remainder = values.sort!.length.divmod(2)
    [1] pry(main)*   medians = [values[quotient], values[quotient-(remainder+1) % 2]].uniq
    [1] pry(main)*   medians.length > 1 ? medians.map { |v| v.to_f }.reduce(:+) / 2 : medians[0]
    [1] pry(main)* end
    => nil
    [2] pry(main)> values = [1,2,3]
    => [1, 2, 3]
    [3] pry(main)> get_median values
    => 2
    [4] pry(main)> values << 4
    => [1, 2, 3, 4]
    [5] pry(main)> get_median values
    => 2.5
    [6] pry(main)> get_median values << -1
    => 2
    [7] pry(main)> values
    => [-1, 1, 2, 3, 4]
    [8] pry(main)> values << 11
    => [-1, 1, 2, 3, 4, 11]
    [9] pry(main)> get_median values << -1
    => 2
    [10] pry(main)> values
    => [-1, -1, 1, 2, 3, 4, 11]
    [11] pry(main)> values.delete_if { |v| v == -1}
    => [1, 2, 3, 4, 11]
    [12] pry(main)> values << -1
    => [1, 2, 3, 4, 11, -1]
    [13] pry(main)> get_median values
    => 2.5
    [14] pry(main)>
    

    【讨论】:

    • 尝试一些简单的测试用例,你知道答案应该是什么。 [11,10,12] 应该产生 11; [11,10] 应该产生 10.5。
    • 更正了我的测试并在 pry 中发布了我的测试。吸取了我关于在没有真正测试的情况下发布代码的教训。
    【解决方案4】:

    答案如下:

    def get_median(sub_a)
        result = -1
        size = sub_a.size
        if size == 0
            result = 0
        elsif size == 1
            result = sub_a[0]
        elsif size == 2
            result = get_average(sub_a[0], sub_a[1])
        else
            sorted_a = sub_a.sort
            index = size / 2
            if size % 2 == 0
                result = get_average(sorted_a[index - 1], sorted_a[index]);
            else 
                result = sorted_a[index];
            end
        end
    
        '%0.01f' % result
    end
    

    【讨论】:

      猜你喜欢
      • 2014-04-19
      • 2013-09-17
      • 1970-01-01
      • 2020-12-14
      • 1970-01-01
      • 2018-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多