关于fizzbuzz:当我遵循Ruby rubocop样式指南并使用.zero时,方法失败了? 而不是== 0

Method fail when I follow Ruby rubocop style guide and use .zero? instead of == 0

TODO:返回一系列整数,'Fizz','Buzz'或'FizzBuzz'
编写一个方法fizz_buzz,它以number作为参数,并且
将一个number元素的数组从1返回到number,但替换了一些
根据这些规则:

  • 如果该数字可被3整除,则将其替换为'Fizz'
  • 如果该数字可被5整除,则将其替换为'Buzz'
  • 如果该数字可被35整除,则将其替换为'FizzBuzz'

如果我按照rubocop的样式指南使用.zero而不是== 0? 我的方法失败了,我不明白为什么

我的样式编辑解决方案现在失败了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def fizz_buzz(number)
  fail ArgumentError,"#{number} is less than 1" if number < 1
  a = [number]
  while number > 1
    number = number - 1
    a.unshift(number)
    a.map! { |x| (x % 15).zero? ? 'FizzBuzz' : x }
    a.map! { |x| (x % 3).zero? ? 'Fizz' : x }
    a.map! { |x| (x % 5).zero? ? 'Buzz' : x }
  end
  a
end

  should return the array [ 1, 2, 'Fizz' ] for number 3 (FAILED - 1)
  should return the array [ 1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7 ] for number 7 (FAILED - 2)
  should return an array with 'FizzBuzz' at the 15th element of the array (15 is divisible by both 3 and 5) (FAILED - 3)

失败:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  1) fizz_buzz should return the array [ 1, 2, 'Fizz' ] for number 3
     Failure/Error: a.map! { |x| (x % 5).zero? ? 'Buzz' : x }

 NoMethodError:
   undefined method `zero?' for"Fizz":String
 # ./lib/fizz_buzz.rb:12:in `
block in fizz_buzz'
 # ./lib/fizz_buzz.rb:12:in `map!'

 # ./lib/fizz_buzz.rb:12:in `fizz_buzz'
 # ./spec/fizz_buzz_spec.rb:13:in `block (2 levels) in <top (required)>'

  2) fizz_buzz should return the array [ 1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7 ] for number 7
     Failure/Error: a.map! { |x| (x % 5).zero? ? 'Buzz' : x }

 NoMethodError:
   undefined method `zero?' for"Fizz":String
 # ./lib/fizz_buzz.rb:12:in `
block in fizz_buzz'
 # ./lib/fizz_buzz.rb:12:in `map!'

 # ./lib/fizz_buzz.rb:12:in `fizz_buzz'
 # ./spec/fizz_buzz_spec.rb:17:in `block (2 levels) in <top (required)>'

  3) fizz_buzz should return an array with 'FizzBuzz' at the 15th element of the array (15 is divisible by both 3 and 5)
     Failure/Error: a.map! { |x| (x % 5).zero? ? 'Buzz' : x }

 NoMethodError:
   undefined method `zero?' for"Fizz":String
 # ./lib/fizz_buzz.rb:12:in `
block in fizz_buzz'
 # ./lib/fizz_buzz.rb:12:in `map!'

 # ./lib/fizz_buzz.rb:12:in `fizz_buzz'
 # ./spec/fizz_buzz_spec.rb:21:in `block (2 levels) in <top (required)>'

我的工作方案风格失败了

1
2
3
4
5
6
7
8
9
10
11
12
def fizz_buzz(number)
  fail ArgumentError,"#{number} is less than 1" if number < 1
  a = [number]
  while number > 1
    number = number - 1
    a.unshift(number)
    a.map! { |x| (x % 15) == 0 ? 'FizzBuzz' : x }
    a.map! { |x| (x % 3) == 0 ? 'Fizz' : x }
    a.map! { |x| (x % 5) == 0 ? 'Buzz' : x }
  end
  a
end

鉴于解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# def fizz_buzz(number)
#   fail ArgumentError,"#{number} should be greater than 1" if number < 1
#   (1..number).map do |i|
#     if (i % 3).zero? && (i % 5).zero?
#       'FizzBuzz'
#     elsif (i % 3).zero?
#       'Fizz'
#     elsif (i % 5).zero?
#       'Buzz'
#     else
#       i
#     end
#   end
# end


现在我们看到了失败的代码,这就是它失败的原因:

你有一个数组a,我想你打算包含结果。您将数字添加到其中,并修复需要说"Fizz"或"Buzz"或"FizzBu??zz"的数字。这可以工作,但是对于一个严重的失败:你在循环的每次迭代中处理数组。如果你刚刚修好它,就在它返回之前,那就没问题了。但是,这样,会发生什么(例如输入值4):

  • 4启动数组
  • 你运行修复,但4是好的,不需要修复
  • 你先加3
  • 你运行修复;数组现在是["Fizz", 4]。到现在为止还挺好。
  • 你先加2;数组是[2,"Fizz", 4]
  • 你运行修复程序。 2在没有干预的情况下通过,然后是"Fizz"
  • "Fizz"不是数字,因此不要调用余数运算符Number#%,而是调用格式运算符String#%。字符串"Fizz"中没有格式符号,因此格式化操作符不会产生任何有趣的内容并返回字符串"Fizz"
  • 然后你测试它是否为零。当您尝试"Fizz" == 0时,它将是"Duh,no"并且只返回false,因为所有类(以BasicObject开头)都定义#==。但是"Fizz".zero?失败了,因为与Number#zero?不同,String#zero?不是一回事。