Andrew Grimm
Andrew Grimm

Reputation: 81510

Is there an equivalent of Array#find_index for the last index in ruby?

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

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

Upvotes: 19

Views: 17575

Answers (6)

Mohiuddin Ahmad Khan
Mohiuddin Ahmad Khan

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

Nakilon
Nakilon

Reputation: 35074

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

Upvotes: 25

hellvinz
hellvinz

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

not an ai
not an ai

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

not an ai
not an ai

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

Chubas
Chubas

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

Related Questions