在 ruby 中查找匹配数组元素的索引

Finding index of matching array elements in ruby

这是我的任务:

输入:来自键盘的数字列表

输出:列表中第二小的数字及其在列表中的位置,其中 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

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

很抱歉,我是 ruby

的新手

Ruby 在 Enumerable and Enumerator, specifically Enumerator#with_index and Enumerable#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 方法 return 是一个 Enumerator 如果你不给它传递一个块,它允许你链接 with_index,传递它的可选参数 offset1,所以第一个元素是索引 1 而不是索引 0。

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

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


如果您想要其他变化,您可以使用 min_by 及其 return 值进行更多尝试,例如,如果您只想要第三小的值,您可以这样做:

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

同样的事情,除了开头的 splat 运算符 *,将除最后一个元素之外的所有元素都放入那个 "unused" 变量中。如果你想要第二和第三小,你可以这样做:

*_, (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 个 return 值并将其存储在变量中。或者只是

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

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

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