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

时间:2022-08-14 04:19:03

I am trying to return the index's to all occurrences of a specific character in a string using Ruby. A example string is "a#asg#sdfg#d##" and the expected return is [1,5,10,12,13] when searching for # characters. The following code does the job but there must be a simpler way of doing this?

我试图使用Ruby将索引返回到字符串中出现的所有特定字符。当搜索#字符时,一个示例字符串是“#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

5 个解决方案

#1


15  

s = "a#asg#sdfg#d##"
a = (0 ... s.length).find_all { |i| s[i,1] == '#' }

#2


15  

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

ETA: This works by creating an Enumerator that uses scan(/#/) as its each method.

ETA:通过创建一个枚举器来工作,该枚举器使用scan(/#/)作为其每个方法。

scan yields each occurence of the specified pattern (in this case /#/) and inside the block you can call Regexp.last_match to access the MatchData object for the match.

扫描将生成指定模式的每个出现情况(在本例中是/#/),并且在块中可以调用Regexp。last_match访问匹配的MatchData对象。

MatchData#begin(0) returns the index where the match begins and since we used map on the enumerator, we get an array of those indices back.

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

#3


13  

Here's a less-fancy way:

这是一个比较普通的道:

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

In a quick speed test this was about 3.3x faster than FM's find_all method, and about 2.5x faster than sepp2k's enum_for method.

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

#4


2  

Here's a long method chain:

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

"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]

requires 1.8.7+

需要1.8.7 +

#5


1  

Another solution derived from FMc's answer:

FMc的另一种解决方案是:

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

I love that Ruby never has only one way of doing something!

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

#1


15  

s = "a#asg#sdfg#d##"
a = (0 ... s.length).find_all { |i| s[i,1] == '#' }

#2


15  

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

ETA: This works by creating an Enumerator that uses scan(/#/) as its each method.

ETA:通过创建一个枚举器来工作,该枚举器使用scan(/#/)作为其每个方法。

scan yields each occurence of the specified pattern (in this case /#/) and inside the block you can call Regexp.last_match to access the MatchData object for the match.

扫描将生成指定模式的每个出现情况(在本例中是/#/),并且在块中可以调用Regexp。last_match访问匹配的MatchData对象。

MatchData#begin(0) returns the index where the match begins and since we used map on the enumerator, we get an array of those indices back.

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

#3


13  

Here's a less-fancy way:

这是一个比较普通的道:

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

In a quick speed test this was about 3.3x faster than FM's find_all method, and about 2.5x faster than sepp2k's enum_for method.

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

#4


2  

Here's a long method chain:

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

"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]

requires 1.8.7+

需要1.8.7 +

#5


1  

Another solution derived from FMc's answer:

FMc的另一种解决方案是:

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

I love that Ruby never has only one way of doing something!

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