查找红宝石中匹配数组元素的索引



这是我的任务:

输入:键盘上的数字列表

输出:列表中第二小的数字,以及它在列表中的位置,其中 1 是第一个数字的位置。

这是我到目前为止的代码:

values = []
print "Enter a number: "
a = gets.chomp.to_i
values.push(a)
print "Enter another number: "
b = gets.chomp.to_i
values.push(b)
print "Enter another number: "
c = gets.chomp.to_i
values.push(c)
print "Enter a final number: "
d = gets.chomp.to_i
values.push(d)
new_values = values.sort
second_smallest = new_values[1]
puts "Second smallest number: #{second_smallest}"
if values.include? second_smallest
print "found matching element"
end

我能够从排序的副本中抓取第二小的元素,然后在原始数组中检查该元素。如何抓取原始数组中匹配元素的索引并打印给用户?

对不起,如果很简单,我是红宝石的新手

def second_smallest(arr)
smallest = arr.min
arr.each_with_index.reject { |n,_| n == smallest }.min_by(&:first)
end
second_smallest [3, 1, 4, 1, 2, 3, 5] #=> [2, 4]
second_smallest [1, 1, 1]             #=> nil
second_smallest []                    #=> nil

在第一个示例中,第二小的数字显然是2

Ruby在EnumerableEnumerator上有几个方便的方法,特别是Enumerator#with_indexEnumerable#min_by。因此,您可以执行以下操作:

_, (value, position) = values.each.with_index(1).min_by(2) { |value, _| value }
puts "Second smallest number is #{value} found at position #{position}"

如果你不给它一个块,each方法会返回一个Enumerator,这允许你链接with_index,用1传递它的可选参数offset,所以第一个元素是索引 1 而不是索引 0。

现在,枚举器将对[value's element, index]集合进行操作,我们就此调用min_by,告诉它我们想要 2 个最小值,并将块参数中的参数拆分为value和 ruby 的"未使用"变量_。那么,如果我们忽略指数,为什么还要调用with_index呢?好吧,现在min_by返回具有 2 个最小value's element[value's element, index],我们将最小的分流回"未使用的"变量_,让 ruby 将下一个数组(第二个最小的数组)转换为 2 个变量valueposition,分别包含最小的元素和索引(我倾向于使用 position 来表示某物是基于 1 的,索引来表示它是基于 0 的, 但这只是个人怪癖)。然后我们可以将它们显示给最终用户。

但是请注意,在调用此数组之前,您不希望values数组进行排序。如果这样做,您将始终看到第二个最小的元素位于位置 2。(所以在你的示例代码中,你想处理values而不是new_valuesnew_values消失了)


如果你想要其他变体,你可以更多地使用min_by及其返回值,例如,如果你只想要第三个最小的值,你可以这样做:

*_, (value, position) = values.each.with_index(1).min_by(3) { |value, _| value }

同样的事情,除了 splat 运算符在开始时*,将除最后一个元素之外的所有元素放入该"未使用"变量中。如果你想要第二和第三小,你可以做:

*_, (second_smallest_value, second_smallest_position), (third_smallest_value, third_smallest_position) = values.each.with_index(1).min_by(3) { |value, _| value }

解构并在变量中存储min_by的最后 2 个返回值。或者只是

*_, second_smallest, third_smallest = values.each.with_index(1).min_by(3) { |value, _| value }

存储数组而不将它们解构为单个变量(因为它开始变得拗口)

最新更新