获取数组元素的索引比O(n)更快

gmi*_*ile 103 ruby arrays indexing performance

鉴于我有一个巨大的数组,以及它的值.我想得到数组中的值的索引.还有其他方式,而不是打电话Array#index来获得它吗?问题来自需要保持真正庞大的阵列和Array#index大量的时间.

经过几次尝试后,我发现通过存储带有字段而不是值本身的结构来缓存元素内部的索引(value, index)会给性能带来巨大的进步(20倍的胜利).

我仍然想知道是否有更方便的方法来查找en元素的索引而不进行缓存(或者有一个很好的缓存技术可以提高性能).

Rog*_*ger 199

为什么不使用索引或rindex?

array = %w( a b c d e)
# get FIRST index of element searched
puts array.index('a')
# get LAST index of element searched
puts array.rindex('a')
Run Code Online (Sandbox Code Playgroud)

index:http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-index

rindex:http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-rindex

  • 这正是OP所说的他们不想要的,因为它们的阵列很大.Array #index为O(n),多次执行会导致性能下降.散列查找是O(1). (12认同)
  • @tim,我不记得在我回答的时候这是**同样的**问题,也许OP后来修改了这个问题,这将使这个答案无效. (4认同)
  • 难道不是说它在特定时间被编辑了吗? (3认同)

saw*_*awa 118

将数组转换为哈希值.然后寻找钥匙.

array = ['a', 'b', 'c']
hash = Hash[array.map.with_index.to_a]    # => {"a"=>0, "b"=>1, "c"=>2}
hash['b'] # => 1
Run Code Online (Sandbox Code Playgroud)

  • 根据您的使用情况,如果存在重复值,则可能会出现问题.上面描述的方法将返回等价或#rindex(最后出现的值)要获得#index等效结果,这意味着哈希返回值的第一个索引,您需要在创建之前沿着反转数组的行做某事哈希然后从初始数组的总长度中减去返回的索引值 - 1.#(array.length - 1) - hash ['b'] (17认同)
  • 如果阵列很长,最快 (2认同)
  • 转换成哈希值是否需要O(n)时间?我想如果它不止一次被使用,那么哈希转换将更加高效.但是对于单次使用,是否与迭代数组没有什么不同? (2认同)

hol*_*eap 9

其他答案没有考虑在数组中多次列出条目的可能性.这将返回一个散列,其中每个键是数组中的唯一对象,每个值都是一个索引数组,对应于对象所在的位置:

a = [1, 2, 3, 1, 2, 3, 4]
=> [1, 2, 3, 1, 2, 3, 4]

indices = a.each_with_index.inject(Hash.new { Array.new }) do |hash, (obj, i)| 
    hash[obj] += [i]
    hash
end
=> { 1 => [0, 3], 2 => [1, 4], 3 => [2, 5], 4 => [6] }
Run Code Online (Sandbox Code Playgroud)

这样可以快速搜索重复的条目:

indices.select { |k, v| v.size > 1 }
=> { 1 => [0, 3], 2 => [1, 4], 3 => [2, 5] }
Run Code Online (Sandbox Code Playgroud)


Eri*_*son 6

是否有充分的理由不使用哈希?查找是阵列的O(1)vs.O(n)