Get index of array element faster than O(n)

前端 未结 8 1317
春和景丽
春和景丽 2020-12-07 09:28

Given I have a HUGE array, and a value from it. I want to get index of the value in array. Is there any other way, rather then call Array#index to get it? The p

相关标签:
8条回答
  • 2020-12-07 09:59

    Other answers don't take into account the possibility of an entry listed multiple times in an array. This will return a hash where each key is a unique object in the array and each value is an array of indices that corresponds to where the object lives:

    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] }
    

    This allows for a quick search for duplicate entries:

    indices.select { |k, v| v.size > 1 }
    => { 1 => [0, 3], 2 => [1, 4], 3 => [2, 5] }
    
    0 讨论(0)
  • 2020-12-07 10:00

    Convert the array into a hash. Then look for the key.

    array = ['a', 'b', 'c']
    hash = Hash[array.map.with_index.to_a]    # => {"a"=>0, "b"=>1, "c"=>2}
    hash['b'] # => 1
    
    0 讨论(0)
  • 2020-12-07 10:06

    Still I wonder if there's a more convenient way of finding index of en element without caching (or there's a good caching technique that will boost up the performance).

    You can use binary search (if your array is ordered and the values you store in the array are comparable in some way). For that to work you need to be able to tell the binary search whether it should be looking "to the left" or "to the right" of the current element. But I believe there is nothing wrong with storing the index at insertion time and then using it if you are getting the element from the same array.

    0 讨论(0)
  • 2020-12-07 10:07

    Is there a good reason not to use a hash? Lookups are O(1) vs. O(n) for the array.

    0 讨论(0)
  • 2020-12-07 10:09

    Taking a combination of @sawa's answer and the comment listed there you could implement a "quick" index and rindex on the array class.

    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
    
    0 讨论(0)
  • 2020-12-07 10:11

    Why not use index or 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')
    

    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

    0 讨论(0)
提交回复
热议问题