Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 获取数组元素索引的速度快于O(n)_Ruby_Arrays_Performance_Indexing - Fatal编程技术网

Ruby 获取数组元素索引的速度快于O(n)

Ruby 获取数组元素索引的速度快于O(n),ruby,arrays,performance,indexing,Ruby,Arrays,Performance,Indexing,假设我有一个巨大的数组,并从中得到一个值。我想得到数组中值的索引。有没有其他方法,而不是调用Array#index来获取它?这个问题源于需要保留真正庞大的数组并调用array#index大量的次数 经过几次尝试后,我发现通过使用(value,index)字段(而不是值本身)存储结构来缓存元素内部的索引,可以在性能上迈出一大步(是win的20倍) 我仍然想知道是否有一种更方便的方法可以在不缓存的情况下查找en元素的索引(或者有一种好的缓存技术可以提高性能)。有没有一个好的理由不使用散列?查找是数组

假设我有一个巨大的数组,并从中得到一个值。我想得到数组中值的索引。有没有其他方法,而不是调用
Array#index
来获取它?这个问题源于需要保留真正庞大的数组并调用
array#index
大量的次数

经过几次尝试后,我发现通过使用
(value,index)
字段(而不是值本身)存储结构来缓存元素内部的索引,可以在性能上迈出一大步(是win的20倍)


我仍然想知道是否有一种更方便的方法可以在不缓存的情况下查找en元素的索引(或者有一种好的缓存技术可以提高性能)。

有没有一个好的理由不使用散列?查找是数组的
O(1)
O(n)

将数组转换为哈希。然后找钥匙

array = ['a', 'b', 'c']
hash = Hash[array.map.with_index.to_a]    # => {"a"=>0, "b"=>1, "c"=>2}
hash['b'] # => 1

如果它是一个排序的数组,你可以使用二进制搜索算法(
O(logn)
)。例如,使用以下功能扩展Array类:

class Array
  def b_search(e, l = 0, u = length - 1)
    return if lower_index > upper_index

    midpoint_index = (lower_index + upper_index) / 2
    return midpoint_index if self[midpoint_index] == value

    if value < self[midpoint_index]
      b_search(value, lower_index, upper_index - 1)
    else
      b_search(value, lower_index + 1, upper_index)
    end
  end
end
类数组
def b_搜索(e,l=0,u=length-1)
如果较低的索引>较高的索引,则返回
中点指数=(下限指数+上限指数)/2
如果self[中点索引]==值,则返回中点索引
如果值
为什么不使用index或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')
索引:

rindex:


结合@sawa的答案和这里列出的注释,您可以在array类上实现一个“quick”索引和rindex

class Array
  def quick_index el
    hash = Hash[self.map.with_index.to_a]
    hash[el]
  end

  def quick_rindex el
    hash = Hash[self.reverse.map.with_index.to_a]
    array.length - 1 - hash[el]
  end
end

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

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] }
这允许快速搜索重复条目:

indices.select { |k, v| v.size > 1 }
=> { 1 => [0, 3], 2 => [1, 4], 3 => [2, 5] }

如果数组具有自然顺序,请使用二进制搜索

使用二进制搜索

二进制搜索具有
O(logn)
访问时间

以下是如何使用二进制搜索的步骤

  • 您的阵列的顺序是什么?例如,是否按名称排序
  • 使用
    b搜索
    查找元素或索引
代码示例

# assume array is sorted by name!

array.bsearch { |each| "Jamie" <=> each.name } # returns element
(0..array.size).bsearch { |n| "Jamie" <=> array[n].name } # returns index
#假设数组按名称排序!
array.bsearch{| each |“Jamie”each.name}#返回元素
(0..array.size).b搜索{n |“Jamie”数组[n].name}返回索引
我仍然想知道是否有一种更方便的方法可以在不缓存的情况下查找en元素的索引(或者有一种好的缓存技术可以提高性能)


可以使用二进制搜索(如果数组是有序的,并且数组中存储的值在某种程度上是可比较的)。为此,您需要能够告诉二进制搜索它应该查看当前元素的“左侧”还是“右侧”。但是我相信在插入时存储
索引
并在从同一数组中获取元素时使用它并没有什么错。

关键是——我在哈希上调用
#键
,它返回我正在使用的数组。不过,我可能也会考虑我的体系结构……如果阵列非常长,则速度最快取决于您的用例,如果存在重复值,则可能会出现问题。上述方法将返回等效或#rindex(值的最后一次出现)以获得#索引等效结果,这意味着散列返回值的第一个索引,您需要在创建散列之前反转数组,然后从初始数组的总长度-1中减去返回的索引值(array.length-1)-散列['b']转换为散列难道不需要O(n)个时间吗?我想如果它被多次使用,那么散列转换的性能会更好。但是对于单次使用,与遍历数组没有什么不同吗?是的,如果真的很重要,那么单次使用可能会更糟,因为哈希计算不会像比较那样快速地短路。这正是OP所说的他们不想要的,因为他们的数组太大了。数组#索引为O(n),多次这样做会降低性能。散列查找是O(1)。@tim,我不记得在我回答的时候这是同一个问题,也许OP后来修改了这个问题,这会使这个答案无效。它不会说它在特定的时间被编辑过吗?呵呵,是的,那是真的。那时候我和另外30个人在看。我猜:/其实读起来并不难。第一部分,如果下限大于上限,则返回(递归已存档)。第二部分通过比较中点m和该点的值与e来检查是否需要左侧或右侧。如果我们没有得到我们想要的答案,我们就会反复出现。我认为这比编辑更有利于人们的自尊心。