I would like to count the number of times "red"
is followed by "green"
in this array:
["red", "orange", "green", "red", "yellow", "blue", "green"]
If it is another color, the code should ignore it and proceed to the next item in the array.
event_type.each_slice(2) do |red, green|
break unless green
count = count + 1
end
p "The count is #{count}"
Step 1:
Look for red
Step 2:
IF not last item
Compare with next item on array
ELSE Go to Step 4
Step 3:
IF green, count = count + 1
Go to Step 1
ELSE Go to Step 2
Step 4:
Print Count
Below one is solution I believe. Sure there is more room to refactor it, you can start from here.
a = ["red", "orange", "green", "red", "yellow", "blue", "green"]
a.reject {|e| !['red', 'green'].include? e }
.each_cons(2)
.select{|e| e == ['red', 'green']}
.size
A more artistic version.
def neither_red_nor_green e
!['red', 'green'].include? e
end
def red_followed_by_green ary
ary == ['red', 'green']
end
a.reject(&method(:neither_red_nor_green))
.each_cons(2)
.select(&method(:red_followed_by_green))
.size
UPDATE
Thanks to @Stefan for below suggestions.
def either_red_or_green e
['red', 'green'].include? e
end
def red_followed_by_green ary
ary == ['red', 'green']
end
a.select(&method(:either_red_or_green))
.each_cons(2)
.count(&method(:red_followed_by_green))
UPDATE
As Stefan Pochmann proposed,
a.select(&method(:either_red_or_green))
.each_cons(2)
.count(['red', 'green'])
will do the same work, without needing another method call.
This is a perfect use-case for Ruby famous flip-flop:
input = %w[red orange green red yellow blue green]
input.reduce(0) do |count, e|
if (e == "red")..(e == "green") and (e == "green")
count + 1 # inc on right boundary
else
count
end
end
#⇒ 2
Also tested on
%w[yellow green green red orange green red yellow blue green red yellow]
FWIW, this is a second question I answered suggesting the flip-flop in a week. The previous one is here.
Clean solution from Stefan Pochmann
input.count { |x| x == "green" if (x == "red")..(x == "green") }
count, _ =
["red", "orange", "green", "red", "yellow", "blue", "green"]
.inject([0, nil]) do |(count, state), word|
if word == "red"
state = :red
elsif word == "green" and state == :red
state = nil
count += 1
end
[count, state]
end
count # => 2
def count_red_to_green(arr)
count = 0
unmatched_red = false
arr.each do |colour|
case colour
when "red"
unmatched_red = true
when "green"
if unmatched_red
count += 1
unmatched_red = false
end
end
end
count
end
count_red_to_green ["red", "orange", "green", "red", "yellow", "blue", "green"]
#=> 2
来源:https://stackoverflow.com/questions/48899497/counting-changes-in-an-array