返回ruby中字符串中所有字符出现的索引

我试图使用Ruby将索引返回到字符串中特定字符的所有出现位置。 示例字符串是"a#asg#sdfg#d##" ,搜索#字符时预期的返回值为[1,5,10,12,13] 。 以下代码完成了这项工作,但必须有一种更简单的方法吗?

 def occurances (line) index = 0 all_index = [] line.each_byte do |x| if x == '#'[0] then all_index << index end index += 1 end all_index end 

 s = "a#asg#sdfg#d##" a = (0 ... s.length).find_all { |i| s[i,1] == '#' } 
 require 'enumerator' # Needed in 1.8.6 only "1#3#a#".enum_for(:scan,/#/).map { Regexp.last_match.begin(0) } #=> [1, 3, 5] 

ETA:这是通过创建一个使用scan(/#/)作为其每个方法的枚举器来实现的。

scan产生指定模式的每次出现(在本例中为/#/ ),在块内部,您可以调用Regexp.last_match来访问匹配的MatchData对象。

MatchData#begin(0)返回匹配开始的索引,因为我们在枚举器上使用了map,我们得到了这些索引的数组。

这是一种不那么花哨的方式:

 i = -1 all = [] while i = x.index('#',i+1) all << i end all 

在快速测试中,这比FM的find_all方法快约3.3倍,比sepp2k的enum_for方法快约2.5倍。

这是一个很长的方法链:

 "a#asg#sdfg#d##". each_char. each_with_index. inject([]) do |indices, (char, idx)| indices << idx if char == "#" indices end # => [1, 5, 10, 12, 13] 

要求1.8.7+

另一个解决方案来自FMc的答案:

 s = "a#asg#sdfg#d##" q = [] s.length.times {|i| q << i if s[i,1] == '#'} 

我喜欢Ruby从来没有一种做事方式!