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