Array#find_index
allows you to find the index of the first item that either
object
, orArray#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?}
В Ruby 1.9.2 Array#rindex
принимает блок: http://apidock.com/ruby/Array/rindex
Какая досада до 1.9.2. В то же время, если вы не хотите перевернуть свой массив, а, скорее, перечислите поиск в обратном порядке, вы можете выполнить
last_index = array.length - 1 - array.rindex.find_index {| item | item.is_wanted? }
(1.8.7 и выше)
Вы можете немного улучшить краткость своего обходного пути, удалив a.length, поскольку отрицательные индексы отсчитываются от конца строки в []
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
По-прежнему кажется ужасно неэффективным перевернуть весь массив, когда все, что вам нужно, - это перебирать его в обратном направлении, но это ваша оценка эффективности и эстетики.
Это немного не по теме, но каждый раз, когда у вас есть коллекция с размером, и вы хотите получить результат другого размера, вы можно использовать инъекцию. В большинстве случаев он позволяет избежать ненужных операций цикла с входной коллекцией.
Например, если я хочу найти индекс последнего нуля:
a = [1,2,nil,6,8,nil,9,nil,10,11,12]
# => [1, 2, nil, 6, 8, nil, 9, nil, 10, 11, 12]
a.inject([-1, nil]){|(current_index, matched), value| current_index += 1; matched = current_index if value.nil?; [current_index, matched]}.last
# => 7
Или вы можете сделать что-то вроде
last_index = array.map {|i| i.is_wanted? }.rindex(true)
, что немного красивее