Reputation: 81510
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?}
Upvotes: 19
Views: 17575
Reputation: 27
First and Last index number can be identified in the following way:
for Integer Array:
irb(main):003:0> month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
=> [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
irb(main):004:0> puts month.first
31
=> nil
irb(main):005:0> puts month.last
31
=> nil
irb(main):006:0> puts month.index(month.first)
0
=> nil
irb(main):007:0> puts month.rindex(month.last)
11
=> nil
irb(main):008:0>
for String Array:
irb(main):013:0> weekDays = Array[ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]
=> ["Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun"]
irb(main):014:0> puts weekDays.first
Mon
=> nil
irb(main):015:0> puts weekDays.last
Sun
=> nil
irb(main):016:0> puts weekDays.index(weekDays.first)
0
=> nil
irb(main):017:0> puts weekDays.rindex(weekDays.last)
6
=> nil
irb(main):018:0>
array.index(element) also can identify the last index number if there is no duplicate/copy element in the array. But I think that it is better to use array.rindex(element) to find out last index number. Originally array.rindex(element) is created to identify the last index number of the similar elements given in an array. For more info: https://rubyapi.org/2.7/o/array#method-i-rindex
Upvotes: 0
Reputation: 35074
In Ruby 1.9.2 Array#rindex
accepts block: http://apidock.com/ruby/Array/rindex
Upvotes: 25
Reputation: 3500
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:
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
Upvotes: 0
Reputation: 1823
Or you could do something like
last_index = array.map {|i| i.is_wanted? }.rindex(true)
which is a bit prettier
Upvotes: 2
Reputation: 1823
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
Upvotes: 0
Reputation: 18043
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)
Upvotes: 1