【问题标题】:In Ruby how do I find the index of one of an array of elements?在 Ruby 中,如何找到元素数组之一的索引?
【发布时间】:2017-05-17 16:40:55
【问题描述】:

在 Ruby 2.4 中,如何在另一个数组中找到一个数组元素的最早索引?也就是说,如果一个数组的任何元素出现在另一个数组中,我想获取第一个索引。我认为 find_index 可能会这样做,但是

a = ["a", "b", "c"]
# => ["a", "b", "c"]
a.find_index("a")
# => 0
a.find_index(["b", "c"])
# => nil

在上面的示例中,我希望看到输出“1”,因为元素“b”出现在数组“a”的索引 1 处。

【问题讨论】:

  • 你在["a", "b", "c"] 中找到"a" 的索引是用a.find_index("a"),那为什么你用a.find_index(["b", "c"]) 而不是a.find_index("b") 来找到"b" 的索引呢? a.find_index(["b", "c"]) 正在数组a 中寻找一个看起来像["b", "c"] 但不存在的元素。那是一个子数组,而不是一个元素。
  • 您是要按顺序查找b,c 的第一次出现,还是只是给定数组中的第一个条目?

标签: arrays ruby


【解决方案1】:

find_index 采用单个元素。您可以通过执行类似

的操作来找到最小值
a = ["a", "b", "c"]
to_find = ["b", "c"]
to_find.map {|i| a.find_index(i) } .compact.min # => 1

【讨论】:

  • @CarySwoveland 对compact 没有真正的看法;我看到它经常使用,对我来说似乎很清楚。另外,仅供参考[nil,nil,nil].compact.min 返回nil。所以没有例外。
  • 我的立场是正确的。谢谢你。由于是错误的,我已经删除了我之前的评论。
【解决方案2】:

您可以使用find_index 并从数组中传递所需的值:

a = ["a", "b", "c"]
p a.find_index('a')
p a.find_index('b')
p a.find_index('c')
# => 0
# => 1
# => 2

您可以使用map 获取a 数组中的每个元素,然后获取每个元素对应的索引:

p a.map{|e| a.find_index(e)}
# => [0, 1, 2]

另一种可能的处理方法是使用Enumerable#each_with_index

a.each_with_index{|e,i| puts "Element: #{e}, Index: #{i}"}
# => Element: a, Index: 0
# => Element: b, Index: 1
# => Element: c, Index: 2

如果要使用["a", "b", "c"] 数组检查["b", "c"] 中每个元素的索引,可以映射第一个,获取数组值,然后使用a,b,c 检查这些索引:

p ["b", "c"].map{|e| ["a", "b", "c"].find_index(e) }
# => [1, 2]

您还可以看到Array#indexEnumerable#find_index

【讨论】:

  • 有人脾气暴躁。我投票赞成恢复宇宙的平衡。我认为这是因为它没有解决用数组调用它的问题。
  • 问题要求返回单个数字(索引),可能用于后续计算。你还没有这样做。我希望这就是反对票的原因。另外,a.map{|e| a.find_index(e)} 没有任何价值。
【解决方案3】:

您可以将Array#index 与块一起使用。

a = ['a', 'b', 'c']
a.index { |x| ['b', 'c'].include?(x) }
#=> 1

引用自文档:

如果给出块而不是参数,则返回块返回 true 的第一个对象的索引。如果没有找到匹配项,则返回 nil。


正如 Cary 在他的评论中指出的那样,将a 中的所有元素与['b', 'c'] 中的所有元素进行比较并不是性能最高的算法(这将导致O(n*m))。根据两个数组的大小,是否可能首先构建更有效的数据结构。使用 Set 而不是 Array 在预先创建 set 时会产生一些成本,但会使块中的比较更快(总体而言 O(n+m)):

require 'set'

a = ['a', 'b', 'c']
set = Set.new(['b', 'c'])
a.index { |x| set.include?(x) }
#=> 1

【讨论】:

  • 如果b = ['b', 'c'],这比枚举ba中寻找匹配更好。如果ab分别包含nm元素,并且a的索引i处的元素是第一个匹配b的元素(i <= n),@987654342 @ 操作是必需的。如果枚举b,则需要n*m 操作。因此,无论nm 如何,这都比枚举b 更快。如果n*m 很大,我建议首先计算require set; sb = b.to_set,然后使用sb.include?(x) 来加速该操作。
【解决方案4】:

您可以在数组a 中找到数组b 的所有元素的索引,并找到最小索引以查找数组b 中的元素在数组a 中首先出现的索引。

如下所示:

a = ["a", "b", "c"]
b = ["b", "c"]

b.map { |x| a.find_index(x) }.min
#=> 1

【讨论】:

    猜你喜欢
    • 2011-06-25
    • 2015-08-19
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-29
    • 1970-01-01
    • 2010-12-04
    相关资源
    最近更新 更多