ruby:当总和为21时,添加数字并打印为true

这是rubeque.com上给出的一个简单问题:编写一个接受任意数量整数的方法,如果总和为21,则将它们添加为true。否则返回False。 它测试输入:

assert_equal twenty_one?(3, 4, 5, 6, 3), true assert_equal twenty_one?(3, 11, 10), false 

这是我到目前为止所拥有的:

 def twenty_one?(*nums) nums.inject(&:+) end if twenty_one? == 21 puts true else false end 

但我收到错误消息:

 RuntimeError: The value '21' does not equal 'true'. 

我真的很困惑如何解决这个问题。 是否可以将if / else语句放在方法中? 如果这个问题非常基本,那就很抱歉。 我是编程新手。

你需要把你的方法写成

 def twenty_one?(*nums) nums.inject(&:+) == 21 end 

这是一个小小的演示: –

 require "minitest/autorun" class Numerics def twenty_one?(*nums) nums.inject(&:+) == 21 end end class TestNumerics < MiniTest::Test def setup @numeric = Numerics.new end def teardown @numeric = nil end def test_twenty_one? assert_equal @numeric.twenty_one?(3, 4, 5, 6, 3), true assert_equal @numeric.twenty_one?(3, 11, 10), false end end 

让我们进行测试: -

 [arup@Ruby]$ ruby test/test_numerics.rb Run options: --seed 61602 # Running: . Finished in 0.001332s, 750.9402 runs/s, 1501.8804 assertions/s. 1 runs, 2 assertions, 0 failures, 0 errors, 0 skips [arup@Ruby]$ 

在你的方法中,它返回了Fixnum实例21 ,你试图将其与true进行比较。 这就是你得到错误的原因。 如果你看一下assert_equal的来源,你会发现两个对象之间的比较是同一个类的实例,否则会抛出你得到的错误。

注意:您当然也可以将此nums.inject(&:+)写为nums.inject(:+)因为Ruby允许这种自由,特别是开箱即用的nums.inject(:+)方法。

更新

Carles Jove Buxeda提出了一个很好的想法来设计这个问题。 我们的想法是将方法放在模块中,然后包含它来测试它的方法:

 require "minitest/autorun" module Numerics def twenty_one?(*nums) nums.inject(:+) == 21 end end class TestNumerics < MiniTest::Test include Numerics def test_twenty_one? assert_equal twenty_one?(3, 4, 5, 6, 3), true assert_equal twenty_one?(3, 11, 10), false end end 

现在,如果我运行它:

 arup_ruby$ ruby test/test_numerics.rb Run options: --seed 1223 # Running: . Finished in 0.001067s, 937.2071 runs/s, 1874.4142 assertions/s. 1 runs, 2 assertions, 0 failures, 0 errors, 0 skips arup_ruby$ 

很酷的主意!

奥雅纳的答案很棒。 我建议让它更通用一点。

 def twenty_one?(*nums) nums.inject(&:+) == 21 end def compare_value_with_sum_of_nums?(value, *nums) nums.inject(&:+) == value end 

我的名字很糟糕。 这让我觉得将方法名称与元编程和gem 人性化结合起来会很酷。 然后,您可以拥有动态方法名称,并从方法名称推断总和应该加起来的值。 所以你可以进行任何比较,比如

MyAwesomeGem.three_thousand_and_twenty_four?(3000,20,4)

建造会很有趣!

🙂