In ruby you can use string#index as follows:
str = “some text”
str.index(/t/)
=>5
But what if I want to get all the indices for a regex in the string?
Is there an string#all_indices method?
I wrote the following, which works, but there must be a more elegant
way:
class String
def all_indices(regex)
indices = []
index = 0
while index && index < self.length #index will be nil upon first
match failure, otherwise quit loop when index is equal to string
length
index = self.index(regex, index)
if index.is_a? Numeric #avoids getting a nil into the indices
array
indices << index
index +=1
end
end
indices
end
end
p “this is a test string for the ts in the worldt”.all_indices(/t/)
p “what is up with all the twitter hype”.all_indices(/w/)
In ruby you can use string#index as follows:
str = “some text”
str.index(/t/)
=>5
But what if I want to get all the indices for a regex in the string?
Is there an string#all_indices method?
Does this do what you want?
class String
def all_indices(reg)
tmp,idx = [],[]
(0…self.length).each{|x| tmp[x] = self[x…-1]}
tmp.each_with_index{|y,i| idx << i if y =~ /\A#{reg}/}
idx
end
end
p “this is a test string for the ts in the worldt”.all_indices(/th/)
#> [0, 26, 36]
It may not be very fast for very long strings ( I didn’t check).
But for strings like your example it seems OK.
In ruby you can use string#index as follows:
str = “some text”
str.index(/t/)
=>5
But what if I want to get all the indices for a regex in the string?
Is there an string#all_indices method?
Facets has:
def index_all(s, reuse=false)
s = Regexp.new(Regexp.escape(s)) unless Regexp===s
ia = []; i = 0
while (i = index(s,i))
ia << i
i += (reuse ? 1 : $~[0].size)
end
ia
end
[].tap?
you must have defined a tap method for array somewhere. But not in the
code you showed. Can’t run the code without a definition for tap.
Thanks,
Tim
(0...self.length).each{|x| idx << x if self[x..-1] =~ /\A#{reg}/}
–
A Look into Japanese Ruby List in Englishhttp://www.kakueki.com/ruby/list.html
This works and the code is more concise than what I had, but it is a
brute force approach that test for matches from every possible
substring. That would be a bit slow.
end
end
p “this is a test string for the ts in the worldt”.all_indices(/t/)
p “what is up with all the twitter hype”.all_indices(/w/)
>> [0, 10, 13, 16, 26, 30, 36, 45]
>> [0, 11, 25]
This is a bit simpler:
class String
def all_indices(substring)
idx = 0
indices = []
loop do
idx = index(substring, idx)
break if idx.nil?
indices << idx
idx += 1
end
indices
end
end
require 'test/unit'
class TestAllIndices < Test::Unit::TestCase
def test_it
assert_equal(
[0, 10, 13, 16, 26, 30, 36, 45],
"this is a test string for the ts in the
worldt".all_indices(/t/)
)
assert_equal(
[0, 11, 25],
“what is up with all the twitter hype”.all_indices(/w/)
)
assert_equal(
[12, 17, 26, 41],
“the quick brown fox jumps over the lazy dog”.all_indices(‘o’)
)
assert_equal(
[1, 3, 5],
“bananana”.all_indices(‘ana’)
)
end
end
[].tap?
you must have defined a tap method for array somewhere. But not in the
code you showed. Can’t run the code without a definition for tap.
Thanks,
Tim
Sorry I am an unconditional one-niner. I really should be more careful
to mark 1.9 only features with comments. At least for some more weeks