如何获取大数组中的子数组索引

时间:2018-06-06 11:49:03

标签: arrays ruby

我有两个数组如下:

a = [1,2,3,4,5,6,7,8,9,10]
b = [3,5,8,10,11]

如果存在数字,我想在主数组中找到子数组的索引。预期的输出是:

res = [2,4,7,9] 

我做了如下:

[3,5,8,10,11].each do |_element|
  res_array = []
  if [1,2,3,4,5,6,7,8,9,10].find_index(_element).present?
   res_array << (header_array.find_index(_element)
  end
  res_array
 end

但我认为有更好的方法来做到这一点。

4 个答案:

答案 0 :(得分:7)

如果性能很重要(例如,如果您的数组巨大),您可以使用each_with_index和{{3}在a中构建所有数字索引对的哈希值}}:

a.each_with_index.to_h
#=> {1=>0, 2=>1, 3=>2, 4=>3, 5=>4, 6=>5, 7=>6, 8=>7, 9=>8, 10=>9}

散列允许更快地获取b中的数字的值(即索引)(与每次遍历数组相反),例如,通过to_h

a.each_with_index.to_h.values_at(*b)
#=> [2, 4, 7, 9, nil]

使用values_at消除nil值:

a.each_with_index.to_h.values_at(*b).compact
#=> [2, 4, 7, 9]

compactslice

a.each_with_index.to_h.slice(*b).values
#=> [2, 4, 7, 9]

答案 1 :(得分:5)

b.map { |e| a.index(e) }.compact
#⇒ [2, 4, 7, 9]

或更简洁:

b.map(&a.method(:index)).compact

答案 2 :(得分:0)

这是另一个更简单的解决方案,

indxs = a.each_with_index.to_h
(a&b).map{|e| indxs[e]}

答案 3 :(得分:0)

到目前为止,所有答案都会遍历所有a(@ Stefan's)或遍历全部或部分a b.size次。我的回答遍历了部分或全部a一次。 a较大时相对有效,b相对于a较小,b中的所有元素都显示在a中。

我的解决方案在a的排序方式特别有效,b的元素通常出现在a的开头。例如,a可能是通过降低一般人群中出现频率排序的姓氏列表(例如,['smith', 'jones',...]),而b是要查找的姓​​名列表{ {1}}。

aa可能包含重复项 1 ,并且b的所有元素都不会保证在b中。我认为a不是空的。

<强>代码

b

我将require 'set' def lookup_index(a, b) b_set = b.to_set b_hash = {} a.each_with_index do |n,i| next unless b_set.include?(n) b_hash[n] = i b_set.delete(n) break if b_set.empty? end b_hash.values_at(*b) end 转换为一个集合,使查找速度与哈希查找速度相当(考虑到使用底层哈希实现集合,这应该不会令人惊讶)。当然,散列查找速度非常快。

<强>实施例

b

请注意,在此示例中,a = [1,2,3,4,5,6,7,8,9,10,8] b = [3,5,8,10,11,5] a都包含重复项b 11b中不存在a

lookup_index(a, b)
  #=> [2, 4, 7, 9, nil, 4]

观察返回的数组包含索引4两次,5中的每个b一次。此外,数组包含nil索引4,以显示b[4] #=> 11中未显示a。如果没有nil占位符,则无法将b的元素映射到a中的索引。但是,如果不需要nil占位符,则可以将b_hash.values_at(*b)替换为b_hash.values_at(*b).compact,或者,如果不需要重复,则替换为b_hash.values_at(*b).compact.uniq

作为第二个例子,假设我们得到以下内容。

a = [*1..10_000]
b = 10.times.map { rand(100) }.shuffle
  #=> [30, 62, 36, 24, 41, 27, 83, 61, 15, 55]
lookup_index(a, b)
  #=> [29, 61, 35, 23, 40, 26, 82, 60, 14, 54]

此处的解决方案是在枚举83的第一个a元素后找到的。

1如果a和/或b中不允许重复,我的解决方案将无法提高效率。