Ruby:如何找到最小数组元素的索引?

27

有没有更优雅的方式来重写这段代码?我认为这是一段糟糕的代码,应该进行重构。

>> a = [2, 4, 10, 1, 13]
=> [2, 4, 10, 1, 13]
>> index_of_minimal_value_in_array = a.index(a.min)
=> 3

1
我不确定这件事。也许是我的过度焦虑。 - kyrylo
1
我会说这几乎是最干净的代码,所以这里不需要“重构”。 - fresskoma
@prostosuper: 我不会删掉它。这基本上是一个自我回答的问题,但是无论如何,试图在数组中获取最小元素索引的人可能会发现这个问题很有帮助。因此,只需创建一个回答,读作“显然没有比a.index(a.min)更好的解决方案”,并接受它 :) - fresskoma
8
如果数组中有多个最小值,你想要第一个、最后一个还是全部?顺便说一下,我认为这是一个值得思考的问题。 - Andrew Grimm
哇!你发现了新的方法。我没想到过!我读了你提到的内容,完全忘记了这个细节。但是,其实我只需要找到数组中的第一个最小元素。阅读其他情况(查找所有和仅查找最后一个最小元素)也会很有趣。 - kyrylo
2
@prostosuper:您能提一下为什么你首先要找到索引吗?如果您能描述更广泛的问题,也许需要采用不同的方法。 - Andrew Grimm
4个回答

52

我相信这个方法只会遍历整个数组一次,并且代码仍然易于阅读:

numbers = [20, 30, 40, 50, 10]           # => [20, 30, 40, 50, 10]
elem, idx = numbers.each_with_index.min  # => [10, 4]

1
简洁的解决方案。不幸的是,Array#last 使它看起来很丑 (ary.each_with_index.min.last)。 - kyrylo
也许 ary.each_with_index.min.second 更加优美。 - Obromios

9

这种方法只遍历一次数组,而使用 ary.index(ary.min) 则需要遍历两次:

ary.each_with_index.inject(0){ |minidx, (v,i)| v < a[minidx] ? i : minidx }

ary.each_with_index.inject([Float::INFINITY,0]) { |(mv,mi), (v,i)| v<mv ? [v,i] : [mv,mi] } - igrek

8

阅读其他情况(查找所有且仅最小元素)可能会很有趣。

ary = [1, 2, 1]

# find all matching elements' indexes
ary.each.with_index.find_all{ |a,i| a == ary.min }.map{ |a,b| b } # => [0, 2]
ary.each.with_index.map{ |a, i| (a == ary.min) ? i : nil }.compact # => [0, 2]

# find last matching element's index
ary.rindex(ary.min) # => 2

在以下代码中,ary.each.with_index… 和 ary.each_with_index… 之间有明显的区别吗?我发现 each_with_index 没有被记录。但是 ary.methods.grep(/each_with_index/); 是正确的。 - kyrylo
1
它们都在Enumerator中有记录,这是Array继承的。each.with_index将数组添加索引,生成一个包含原始元素和索引的数组数组,然后可以将其传递给其他转换器,如mapeach_with_index想要迭代数组数组。这是一个微妙的区别,但我不想要一个each循环,我想要进行转换。 - the Tin Man
1
这个问题不是关于速度的,而是关于实现某事的替代方法。为什么选择这个呢?我不知道。 - the Tin Man

4

我其实很喜欢@andersonvom的回答,它只需要循环一次数组,就可以得到索引。

如果你不想使用ary.each_with_index.min,那么你可以这样做:

ary = [2,3,4,5,1]                                             # => [2,3,4,5,1]
_, index_of_minimal_value_in_array = ary.each_with_index.min  # => [1, 4]
index_of_minimal_value_in_array                               # => 4

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