如何以稳定的顺序查找数组中max n个元素的索引

时间:2018-05-16 20:29:46

标签: arrays ruby

我有一个数字和一个数组:

n = 4
a = [0, 1, 2, 3, 3, 4]

我希望以元素大小的相反顺序找到与n的最大a元素对应的索引,并且在元素大小相等时以稳定的顺序找到。预期的输出是:

[5, 3, 4, 2]

此代码:

a.each_with_index.max(n).map(&:last) 
# => [5, 4, 3, 2]

给出了正确的索引,但改变了顺序。

3 个答案:

答案 0 :(得分:5)

<强>代码

def max_with_order(arr, n)
   arr.each_with_index.max_by(n) { |x,i| [x,-i] }.map(&:last)
end

<强>实施例

a = [0,1,2,3,3,4]

max_with_order(a, 1)  #=> [5]
max_with_order(a, 2)  #=> [5, 3]
max_with_order(a, 3)  #=> [5, 3, 4]
max_with_order(a, 4)  #=> [5, 3, 4, 2]
max_with_order(a, 5)  #=> [5, 3, 4, 2, 1]
max_with_order(a, 6)  #=> [5, 3, 4, 2, 1, 0]

<强>解释

对于n = 3,步骤如下。

b = a.each_with_index
  #=> #<Enumerator: [0, 1, 2, 3, 3, 4]:each_with_index>

我们可以将b转换为数组,以查看它将生成的(六个)值并传递给该块。

b.to_a                
  #=> [[0, 0], [1, 1], [2, 2], [3, 3], [3, 4], [4, 5]]

继续,

c = b.max_by(n) { |x,i| [x,-i] }
  #=> [[4, 5], [3, 3], [3, 4]]
c.map(&:last)
  #=> [5, 3, 4]

请注意arr的元素不一定是数字,只是可比较的。

答案 1 :(得分:4)

您可以向max提供一个区块,以使判断更加具体,如此

a.each_with_index.max(n) do |a,b| 
  if a[0] == b[0] # the numbers are the same
    b[1] <=> a[1] # compare the indexes in reverse
  else
    a[0] <=> b[0] # compare the numbers themselves
  end
end.map(&:last) 
#=> [5,3,4,2]

max阻止预期可比的响应,例如-1,0,1所以在这种情况下我们只是说数字是否相同然后以相反的顺序比较索引,例如4 <=> 3 #=> -1 -1表示此值较小,因此将在3

之后放置

另外要扩展@ CarySwoveland的答案(我有点嫉妒,我没想到),因为你只关心返回索引,我们可以按照以下方式实现,而不需要辅助map

a.each_index.max_by(n) { |x| [a[x],-x] }
#=> [5,3,4,2]

答案 2 :(得分:0)

@compsy你写了没有改变顺序,所以它会是:

a = [0,1,2,3,3,4]
n = a.max
i = 0
a.each do |x|
  break if x == n
  i += 1
end

我使用变量 i 作为索引,当 x (这是分析的值)等于 n 时,我们使用 break 停止每个方法,保留 i 的最后一个值,它对应于数组中最大值的位置。请注意, i 的值因数组中的一个自然位置而不同,这是因为在数组中第一个元素是0而不是1。

打破 每个,因为在找到值的位置后,无需继续检查数组的所有其他值。