数组中的最大值和最小值

5
我写了一段 Ruby 代码来获取数组中的最大值和最小值。该代码正确地打印出了最大值(8),但未打印出最小值(2)。请告诉我我的代码哪里出了问题。
class MaxMinArray
  def MaxMinMethod()
    array = [4,2,8,3,5]
    maxNo = array[0]
    minNo = array[0]
    arrayLength = array.length
    for i in 1..arrayLength
      if array[i].to_i > maxNo
        maxNo = array[i]
      end
      if array[i].to_i < minNo
        minNo = array[i]
      end
    end
    puts "Maximum no. in the given array: " + maxNo.to_s
    puts "Minimum no. in the given array: " + minNo.to_s
  end
end

MaxiMinArrayObj = MaxMinArray.new
MaxiMinArrayObj.MaxMinMethod()

1
请参阅Enumerable#max和#min..即使您无法使用它们,使用折叠(#reduce)编写最大/最小值比Java风格的循环更加优雅。xD - user2864740
在Ruby中,我们不使用CamelCase来命名方法,而是使用snake_case。MaxMinMethod应该改为max_min_method。另外,显然这是一个方法,所以可以简单地称其为max_min。但是,正如其他人提到的,Ruby已经实现了minmax,因此不必自己编写,可以利用预先编写好的方法。 - the Tin Man
if array[i].to_i > maxNoif array[i].to_i < minNo中您使用了整数转换。在maxNo = array[i]minNo = array[i]中,您没有使用它(to_i)。这种错误可能很难找到。我会写成这样:for i in 1...array.length; candidate = array[i].to_i; if candidate > maxNo; # 其余的代码. Sawa谈到了类似的事情:https://dev59.com/SYDba4cB1Zd3GeqPGqLA#24216271 - Darek Nędza
你的问题是否已经得到解决? - Jorge de los Santos
7个回答

6

我知道你正在学习编程,但是在学习的过程中,学会利用现有的解决方案也很重要。重新发明轮子只会浪费你的时间来调试代码。

我会这样编写代码:

def max_min(ary)
  [ary.max, ary.min]
end

max_min([1,2,4]) # => [4, 1]

不过,再说一遍,Ruby已经有一个很好的minmax方法:

[1,2,4].minmax # => [1, 4]

请使用它,并将精力集中在更有趣的事情上。

如果你必须按相反的顺序查看这些值,请使用:

[1,2,4].minmax.reverse # => [4, 1]

一个更加冗长/老派的做法是:
FIXNUM_MAX = (2 ** (0.size * 8 - 2) - 1)
FIXNUM_MIN = -(2 ** (0.size * 8 - 2))

def max_min(ary)
  return [nil, nil] if ary.empty?
  minval = FIXNUM_MAX
  maxval = FIXNUM_MIN
  ary.each do |i|
    minval = i if i < minval
    maxval = i if i > maxval
  end
  [maxval, minval]
end

max_min([1,2,4]) # => [4, 1]
[1,2,4].minmax.reverse # => [4, 1]

这个函数简单地遍历数组,检查每个值是否比上一个最小或最大值更小或更大,如果是,则记住它。一旦数组耗尽,就返回这些值。使用each更加简洁,因为它消除了使用索引值遍历数组的许多麻烦。在Ruby中,我们几乎从不使用for,特别是用它来遍历数组。

(技术上说,Ruby可以保存远远超过4611686018427387903和-4611686018427387904的值,这是FIXNUM_MAXFIXNUM_MIN的值,但对于我们想做的大多数事情来说,这已经足够了。)


1
ary为空时,您的冗长方法返回错误结果。我不明白为什么您需要使用FIXNUM_MAXFIXNUM_MIN - sawa
1
就像我所说的,这是我们在旧时代的做法。编程语言对于整数类型有最大/最小值限制,因为它们与CPU支持的硬件相关,而且不像Ruby可以随意更改精度。我们必须知道边界并使用相反端点来设置最小/最大值。至于返回空数组的值,很容易修复。 - the Tin Man

6
这是两件事情的结合体。
首先,你遍历了 `for i in 1..arrayLength`,这个循环会遍历到 `array` 的最后一个元素之后。在最后一个元素之后,`array[i]` 就变成了 `nil`。
其次,你有一个条件 `if array[i].to_i < minNo`,即使 `array[i]` 不是数字也可以满足。
因此,在最后一个元素之后返回的 `nil` 满足条件,因为 `nil.to_i` 是 `0`,并且将该 `nil` 赋值给 `minNo`。

5

只要你可能想要将结果用于其他地方,就不应该在方法内部打印输出。

Ruby还提供了各种神奇的方法来获取数组的最大值和最小值:

results = [5, 23, 43, 2, 3, 0].minmax
puts "Maximum no. in the given array: " + results[1]
puts "Minimum no. in the given array: " + results[0]

7
Ruby有一个更加神奇的方法:min, max = [1,2,3].minmax - Michael Kohl

2

你需要从1到arrayLength - 1进行迭代(这是最后一个元素的索引)。你可以使用三个点来表示:

for i in 1...arrayLength

为什么要使用索引呢? - user2864740
你遇到的错误涉及到 i 值超出了数组边界。因此,array[i].to_i 的值为 0,这比数组中的任何值都要小。然后在下一行中,你将 nil 赋值给 minNo 变量。 - Christopher Bradford
1
你的解释修复了这个 bug,我只是想提供一些额外的信息。 - Christopher Bradford
我也用Java写了同样的代码,但是在数组长度上没有加-1也能正常运行。 - ChnMys
你有 i = 1; i < ArrLength,它等同于精确地 1...ArrLength.. 包括边界值。 - zishe

1
我在Ruby中使用了这个表达式来获取最小值和最大值,虽然有些牵强,但它能够正常工作。
class RubyMinMax

def self.min_function(array=[])
    puts "my array is the following #{array}"
    puts "the length of the array is #{array.length}"
    it = 0
    while array.length > 1
        array.fetch(it).to_i > array.fetch(it-1).to_i ? array.delete_at(it) : array.delete_at(it-1)
        it = array.length-1
    end
    print array[0]
end

def self.max_function(array=[])
    puts "my array is the following #{array}"
    puts "the length of the array is #{array.length}"
    it = 0
    while array.length > 1
        array.fetch(it).to_i < array.fetch(it-1).to_i ? array.delete_at(it) : array.delete_at(it-1)
        it = array.length-1
    end
    print array[0]
end
end

RubyMinMax.min_function([18, 19, 17])

RubyMinMax.max_function([18, 19, 17])

1
如果我不能使用Ruby的minmax方法,那么我可能会这样做:
array = [4,2,8,3,5]

min, max = nil, nil
array.each do |element|
  min = element if min.nil? || element < min
  max = element if max.nil? || max < element
end

puts [min, max]
# => [2, 8]

0
以最简单的方式,您可以使用数组的maxmin方法。
:001 > [1,4,1,3,4,5].max
 => 5 
:002 > [1,4,1,3,4,5].min
 => 1 

如果你的数组可能包含nil,则首先使用compact,然后使用minmax

例如

:003 > [1,4,1,3,4,5,nil].compact
=> [1, 4, 1, 3, 4, 5]

:004 > [1,4,1,3,4,5].max
 => 5 

:005 > [1,4,1,3,4,5].min
 => 1 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接