Counting changes in an array

Deadly 提交于 2019-12-04 07:06:48

问题


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

回答1:


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.




回答2:


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") }



回答3:


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



回答4:


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!