【问题标题】:Finding index of matching array elements in ruby在 ruby​​ 中查找匹配数组元素的索引
【发布时间】:2018-12-29 18:56:46
【问题描述】:

这是我的任务:

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

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

【问题讨论】:

  • 获取数组中某个值的索引并不难。数组有一个index 方法。

标签: arrays ruby indexing matching


【解决方案1】:
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

【讨论】:

    【解决方案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,传递它的可选参数offset1,所以第一个元素是索引1 而不是索引 0。

    现在,Enumerator 将对 [value's element, index] 的集合进行操作,我们在上面调用 min_by,告诉它我们想要 2 个最小值,并将块参数中的 args 拆分为 value 和ruby 的“未使用”变量_。那么,如果我们忽略索引,为什么要调用with_index?好吧,现在min_by 返回具有 2 个最小 value's element[value's element, index],我们将最小的返回到“未使用”变量 _ 并让 ruby​​ 将下一个数组,第二小的数组变成 2 个变量 @ 987654344@ 和 position 分别包含最小元素和索引(我倾向于使用位置来表示某事物是基于 1 的,而索引意味着它是基于 0 的,但这只是个人的怪癖)。然后我们可以将它们显示给最终用户。

    但请注意,您希望在调用此之前对 values 数组进行排序。如果这样做,您将始终看到第二小的元素位于位置 2。(因此,在您的示例代码中,您想要处理 values not new_values,而 new_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 的最后两个返回值。或者只是

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

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

    【讨论】:

    • 你所拥有的是最小的,而不是第二小的。
    • @AndrewMarshall 已修复
    • 如果values = [1,1,2],则在索引1 处获得值1。这很可能是 OP 正在寻找的,但 2 绝对是“第二小的数字”。另外,考虑在min_by 的块之后使用.last
    猜你喜欢
    • 2015-08-19
    • 2020-06-01
    • 2021-11-03
    • 2014-11-15
    • 2023-03-24
    • 1970-01-01
    • 2017-03-06
    • 1970-01-01
    • 2011-02-05
    相关资源
    最近更新 更多