我希望能够使用Ruby在更大的字符串中找到所有出现的子字符串的索引。例如:“爱因斯坦”中的所有“in”
str = "Einstein"
str.index("in") #returns only 1
str.scan("in") #returns ["in","in"]
#desired output would be [1, 6]
答案 0 :(得分:10)
标准黑客是:
"Einstein".enum_for(:scan, /(?=in)/).map { Regexp.last_match.offset(0).first }
#=> [1, 6]
答案 1 :(得分:3)
def indices_of_matches(str, target)
sz = target.size
(0..str.size-sz).select { |i| str[i,sz] == target }
end
indices_of_matches('Einstein', 'in')
#=> [1, 6]
indices_of_matches('nnnn', 'nn')
#=> [0, 1, 2]
第二个例子反映了我对重叠字符串处理的假设。如果不考虑重叠的字符串(即[0, 2]
是第二个例子中所需的返回值),这个答案显然是不合适的。
答案 2 :(得分:2)
这是一个更详细的解决方案,它带来了不依赖于全球价值的优势:
def indices(string, regex)
position = 0
Enumerator.new do |yielder|
while match = regex.match(string, position)
yielder << match.begin(0)
position = match.end(0)
end
end
end
p indices("Einstein", /in/).to_a
# [1, 6]
它会输出Enumerator
,因此您也可以懒惰地使用它,或者只使用n
个第一个索引。
此外,如果您可能需要更多信息而不仅仅是索引,您可以返回Enumerator
MatchData
并提取索引:
def matches(string, regex)
position = 0
Enumerator.new do |yielder|
while match = regex.match(string, position)
yielder << match
position = match.end(0)
end
end
end
p matches("Einstein", /in/).map{ |match| match.begin(0) }
# [1, 6]
要获得@Cary描述的行为,您可以用position = match.begin(0) + 1
替换块中的最后一行。