我希望能够使用Ruby在更大的字符串中找到所有出现的子字符串的索引。例如为:所有“在”中的“爱因斯坦”查找字符串中子字符串的所有索引
str = "Einstein"
str.index("in") #returns only 1
str.scan("in") #returns ["in","in"]
#desired output would be [1, 6]
我希望能够使用Ruby在更大的字符串中找到所有出现的子字符串的索引。例如为:所有“在”中的“爱因斯坦”查找字符串中子字符串的所有索引
str = "Einstein"
str.index("in") #returns only 1
str.scan("in") #returns ["in","in"]
#desired output would be [1, 6]
标准的手段是:
"Einstein".enum_for(:scan, /(?=in)/).map { Regexp.last_match.offset(0).first }
#=> [1, 6]
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]
是期望的返回值),则此答案显然不合适。
简单而干净,可能我会用这个。 – tokland
这是一个更详细的解决方案,它带来了不依赖于全球价值的优势:
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
第一指标。
另外,如果你可能需要的不仅仅是指数的更多信息,你可以返回的MatchData
的Enumerator
并提取指数:
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
的区块内。
不错,一个。注意''nnnn“.enum_for(:scan,/nn/).map {Regexp.last_match.offset(0).first}#=> [0,2]'。如果'[0,1,2]'是所需的返回值,则将正则表达式('/ nn /')更改为'/(?= nn)/'。 –
好点,@Cary。我想在大多数情况下,我们希望第二个更新。 – tokland