Index of the n-th occurrence

Hi, some newbie questions…

  1. How can I obtain all the indices of the occurrences of a pattern in a
    string (and not only the index of the first one using “index”)? And the
    index of the n-th occurrence?

  2. What’s the simplest way to select elements of a vector,on the basis
    of a
    condition on a second vector of the same length?

Thanks,

                  Marco

Alle mercoledì 26 dicembre 2007, Marco ha scritto:

Hi, some newbie questions…

  1. How can I obtain all the indices of the occurrences of a pattern in a
    string (and not only the index of the first one using “index”)? And the
    index of the n-th occurrence?

I’m sure there’s a better solution, but I can’t think of it right now.
For the
first part of your question, notice that String#index (unlike
Array#index)
accept an optional offset argument. You can then do something like:

str =“a test string”

positions = []

pos = -1

while (pos = s.index(your_pattern, pos + 1))
positions << pos
end

After running this code, positions will contain the indices of all the
occurrences of your_pattern (which can be any argument String#index
accepts)
inside str.

To get the index of the n-th occurrence, you can extract the n-th
element from
such an array, or add a counter to the while cycle.

  1. What’s the simplest way to select elements of a vector,on the basis of a
    condition on a second vector of the same length?

It depends on what your needs exactly are. Suppose you have the two
arrays

a1=%w[a b c d]
a2=[2, 3, 5, 6]

and want to get the letters in a1 in the same places of even numbers in
a2
(i.e, [“a”, “d”]).

These are some approaches (you need to do require ‘enumerator’ before
all of
them):

a1.enum_for(:each_with_index).select{|e, idx| a2[idx]%2==0}
=> [[“a”, 0], [“d”, 3]]

This returns an array of the pairs of the letter and its index. You can
then
extract the letters with map.

a1.enum_for(:each_with_index).inject([]){|res, i|
a2[i[1]]%2 == 0 ? res << i[0] : res }
=> [“a”, “d”]

a1.enum_for(:each_with_index).map{|e, idx| a2[idx]%2==0 ? e :
nil}.compact

This will not work if a1 can contain nil elements (because they also
would be
removed by nil).

I hope this helps

Stefano

Marco wrote:

  1. What’s the simplest way to select elements of a vector,on the basis of a
    condition on a second vector of the same length?

res=[]
[1,2,3,4].zip([2,4,9,16]) {|x,y| res << x if y==x*2}
res #=> [1,2]

HTH,
Sebastian

On Dec 26, 1:53 am, “Marco” [email protected] wrote:

Hi, some newbie questions…

  1. How can I obtain all the indices of the occurrences of a pattern in a
    string (and not only the index of the first one using “index”)? And the
    index of the n-th occurrence?

Why do you want these indices? There may be an easier
way to accomplish your goal. Ruby isn’t APL.

a = []
==>[]
“the thug’s thews”.scan(/.*?(th)/){ a << $~.begin(1) }
==>“the thug’s thews”
a
==>[0, 4, 11]

On Dec 26, 8:53 am, “Marco” [email protected] wrote:

Hi, some newbie questions…

  1. How can I obtain all the indices of the occurrences of a pattern in a
    string (and not only the index of the first one using “index”)? And the
    index of the n-th occurrence?

Hi
perhaps you can find something useful in ruby core doc RegExp/
MatchData
it seems that the method offset is good for you

mtch.offset(n) => array

Returns a two-element array containing the beginning and ending
offsets of the nth match.

Tom