Reputation: 15284
I have to search an item in an array and return the value of the next item. Example:
a = ['abc.df','-f','test.h']
i = a.find_index{|x| x=~/-f/}
puts a[i+1]
Is there any better way other than working with index?
Upvotes: 0
Views: 229
Reputation: 34031
The reason something like array.find{something}.next
doesn't exist is that it's an array rather than a linked list. Each item is just it's own value; it doesn't have a concept of "the item after me".
@tokland gives a good solution by iterating over the array with each pair of consecutive items, so that when the first item matches, you have your second item handy. There are strong arguments to be made for the functional style, to be sure. Your version is shorter, though, and I'd argue that yours is also more quickly and easily understood at a glance.
If the issue is that you're using it a lot and want something cleaner and more to the point, then of course you could just add it as a singleton method to a
:
def a.find_after(&test)
self[find_index(&test).next]
end
Then
a.find_after{|x| x=~/-f/}
is a clear way to find the next item after the first match.
All of that said, I think @BenjaminCox makes the best point about what appears to be your actual goal. If you're parsing command line options, there are libraries that do that well.
Upvotes: 3
Reputation: 20408
Your solution working with indexes is fine, as others have commented. You could use Enumerable#drop_while
to get an array from your match on and take the second element of that:
a = ['abc.df','-f','test.h']
f_arg = a.drop_while { |e| e !~ /-f/ }[1]
Upvotes: 0
Reputation: 67860
A classical functional approach uses no indexes (xs.each_cons(2)
-> pairwise combinations of xs):
xs = ['abc.df', '-f', 'test.h']
(xs.each_cons(2).detect { |x, y| x =~ /-f/ } || []).last
#=> "test.h"
Using Enumerable#map_detect simplifies it a litte bit more:
xs.each_cons(2).map_detect { |x, y| y if x =~ /-f/ }
#=> "test.h"
Upvotes: 3
Reputation: 6120
I don't know of a cleaner way to do that specific operation. However, it sure looks like you're trying to parse command-line arguments. If so, I'd recommend using the built-in OptionParser module - it'll save a ton of time and hair-pulling trying to parse them yourself.
This article explains how it works.
Upvotes: 1