1

这是 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 语句放在方法中?对不起,如果这个问题真的很基本。我是编程新手。

4

2 回答 2

5

您需要将方法编写为

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]$

在您的方法中,它返回的是您试图与之比较的Fixnuminstance 。这就是你得到错误的原因。如果您查看 的来源,您会发现两个对象之间的比较是同一类的实例,否则会抛出您得到的错误。21trueassert_equal

注意:你当然也可以这样写nums.inject(&:+),因为 Ruby 在特别是开箱即用的方法nums.inject(:+)的情况下允许这种自由。#reduce/#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$

很酷的主意!

于 2015-01-17T18:33:32.183 回答
0

Arup 的回答很棒。我建议让它更通用一点。

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

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

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

MyAwesomeGem.three_thousand_and_twenty_four?(3000, 20, 4)

建造会很有趣!

:)

于 2015-01-23T10:32:48.363 回答