返回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从来没有一种做事方式!