tags:

views:

60

answers:

5

Array#find_index allows you to find the index of the first item that either

  • is equal to an object, or
  • makes a block passed to it evaluate to true

Array#rindex can allow you to find the index of the last item that is equal to an object, but is there anything that allows you to find the index of the last item that makes a block passed to it return true?

Otherwise, should I do something like

last_index = array.length - 1 - array.reverse.find_index{|item| item.is_wanted?}
+2  A: 

In Ruby 1.9.2 Array#rindex passes block. http://apidock.com/ruby/Array/rindex

Nakilon
+2  A: 

Such a shame it comes until 1.9.2. In the meantime, if you don't want to reverse your array, but rather enumerate the search in reverse, you can do

last_index = array.length - 1 - array.rindex.find_index{|item| item.is_wanted? } (1.8.7 and up)

Chubas
+1  A: 

You could make a marginal conciseness improvement in your workaround by removing a.length, as negative indices count from the end of the string in []

irb(main):015:0> a=[1,2,nil,6,8,nil,9,nil,10,11,12]
=> [1, 2, nil, 6, 8, nil, 9, nil, 10, 11, 12]
irb(main):016:0> -(a.reverse.index(nil)+1)
=> -4
irb(main):017:0> a[-4]
=> nil

It still seems hideously inefficient to reverse the whole array when all you want to do is iterate backwards through it, but that's your efficiency vs aesthetics judgement call

telent
That said, I prefer chubas answer. Didn't notice rindex there ...
telent
+1 very clever..
Anurag
A: 

Or you could do something like

last_index = array.map {|i| i.is_wanted? }.rindex(true)

which is a bit prettier

telent
A: 

this is slightly off topic, but anytime you have a collection with a size and you want a result of another size you can use inject. Most of the times it avoids unecessary loop operations on the input collection.

for instance if i want to find the index of the last nil:

ruby-1.8.7-p174 > a=[1,2,nil,6,8,nil,9,nil,10,11,12]
 => [1, 2, nil, 6, 8, nil, 9, nil, 10, 11, 12] 
ruby-1.8.7-p174 > a.inject([-1, nil]){|(current_index, matched), value| current_index += 1; matched = current_index if value.nil?; [current_index, matched]}.last
 => 7
hellvinz