Reputation: 463
I need to write a method that does the following
consecutive_count("aaabbcbbaaa") == [["a", 3], ["b", 2], ["c", 1], ["b", 2], ["a", 3]]
I got the code, but it looks ugly and I'm trying to see a better solution, please advice.
Here is my code:
def consecutive_count(str)
el = str[0]; count = 0; result = []
str.split("").each do |l|
if (el != l)
result << [el, count]
count = 1
el = l
else
count +=1
end
end
result << [el, count] if !el.nil?
return result
end
Upvotes: 0
Views: 101
Reputation: 13901
Regexp solution:
my_s = "aaabbcbbaaa"
p my_s.scan(/(.)(\1*)/).map{|x,y| [x, y.size + 1]}
#=> [["a", 3], ["b", 2], ["c", 1], ["b", 2], ["a", 3]]
or
a, result = "aaabbcbbaaa", []
result << a.slice!(/(\w)\1*/) until a.empty?
and then map the result with counts.
Upvotes: 0
Reputation: 55758
A solution which does not involve regex magic (although those are a bit shorter and probably faster) is this:
str.each_char.each_with_object([]) do |char, result|
if (result.last || [])[0] == char
result.last[1] += 1
else
result << [char, 1]
end
end
Depending on your level of understanding, it might better transport your intended meaning which might help to debug the thing in 6 month :)
Upvotes: 0
Reputation: 118271
Here is one way :
s = "aaabbcbbaaa"
s.chars.chunk{|e| e }.map{|item,ary| [item,ary.size]}
# => [["a", 3], ["b", 2], ["c", 1], ["b", 2], ["a", 3]]
Upvotes: 3
Reputation: 168091
"aaabbcbbaaa".scan(/(?<s>(?<c>.)\k<c>*)/).map{|s, c| [c, s.length]}
# => [["a", 3], ["b", 2], ["c", 1], ["b", 2], ["a", 3]]
or
"aaabbcbbaaa".scan(/((.)\2*)/).map{|s, c| [c, s.length]}
# => [["a", 3], ["b", 2], ["c", 1], ["b", 2], ["a", 3]]
Upvotes: 3
Reputation: 458
You can try:
def consecutive_count(str)
result = {}
array = str.split(//).uniq
array.each.map {|char| result[char] = 0}
array.each do |char|
while str.starts_with?(char) do
result[char] += 1
str[0] = ""
end
result
end
Upvotes: -1