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

返回ruby中字符串中出现的所有字符的索引,ruby,string,Ruby,String,我试图使用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 en

我试图使用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
def发生(行)
索引=0
所有索引=[]
行。每个字节do | x|
如果x='#'[0],则
全部索引
ETA:这是通过创建一个枚举器来实现的,该枚举器使用
scan(/#/)
作为其每个方法

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


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

这里有一个很长的方法链:

s = "a#asg#sdfg#d##"
a = (0 ... s.length).find_all { |i| s[i,1] == '#' }
"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]
“a#asg#sdfg#d#”。
每个字符。
每个_带有_索引。
注入([])do |索引(char,idx)|
指数[1,5,10,12,13]

需要1.8.7+

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

i = -1
all = []
while i = x.index('#',i+1)
  all << i
end
all
i=-1
全部=[]
当i=x.index(“#”,i+1)

所有根据FMc的答案得出的另一种解决方案:

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

s、 length.times{| i | q这是一个海量字符串的解决方案。我正在对4.5MB文本字符串进行文本查找,而其他解决方案则陷入停顿。这充分利用了ruby.split与字符串比较相比非常有效的事实

def indices_of_matches(str, target)
      cuts = (str + (target.hash.to_s.gsub(target,''))).split(target)[0..-2]
      indicies = []
      loc = 0
      cuts.each do |cut|
        loc = loc + cut.size
        indicies << loc
        loc = loc + target.size
      end
      return indicies
    end
在字符串末尾添加一些内容,以防目标位于末尾(以及拆分的工作方式),但还必须确保“随机”添加不包含目标本身

indices_of_matches("a#asg#sdfg#d##","#")
=> [1, 5, 10, 12, 13]

这些速度数字是从1.8.5开始的。在1.9.1中,这仍然是最快的,但find_all大约慢了3倍,enum_for大约慢了5倍!我快速猜测是
Regexp.last_match.begin(0)
这会减慢
enum_for
方法的速度。(也就是说,我希望
enum_for
本身不是问题。)无论哪种方法,我都喜欢这既简单又可读。少花哨往往更好。这更快,因为在其他方法中,每个字符都会执行一个块。我在1.9中遇到并解决了一个类似的问题,你可以做
。每个字符都有
(而不是
每个字符。每个字符都有
)我认为那样读起来更好。s=“a#asg#sdfg#d####a=(0…s.length)。find|u all{I | s[I]=''.}应该工作得太好了吗?不需要,1…?@SamJoseph在这种情况下,是的,这两个是同义的。
[x,y]
的2参数版本意味着“从code>开始的长度为y的子串”,与
[x]
相同,意思是“x
处的字符(也是字符串,因为ruby没有字符类型)”。
(str + (target.hash.to_s.gsub(target,'')))
indices_of_matches("a#asg#sdfg#d##","#")
=> [1, 5, 10, 12, 13]