【问题标题】:Using the 'pig latin language' in Ruby [closed]在 Ruby 中使用“猪拉丁语”[关闭]
【发布时间】:2015-01-02 02:32:39
【问题描述】:

我正在努力寻找验证这些方法的方法,想知道是否有人知道执行此操作的基本方法?

class PigLatinTest < MiniTest::Unit::TestCase

  def test_word_beginning_with_a
    assert_equal "appleay", PigLatin.translate("apple")
  end

  def test_other_word_beginning_e
    assert_equal "earay", PigLatin.translate("ear")
  end

  def test_word_beginning_with_p
    assert_equal "igpay", PigLatin.translate("pig")
  end

例如第一个可能是:

module PigLatin

  class Word
    def initialize(word)
        @word = word.to_s
    end
    # remember to use the .to_s method

    def translate(word)
        if word[0] == "a" || "e" || "o" || "u" || "i"
            word = word + "ay"
        elsif word[0] != "a" || "e" || "o" || "u" || "i"
            word = word-word[0]+"ay"
        end
    end
  end

  # you can add method here even outside of the class ...
end

------------在另一个文件中

module PigLatin

  class Word

    # remember to use the .to_s method

  end

  # you can add method here even outside of the class ...
end

【问题讨论】:

  • 您需要在您的PigLatin 模块中添加一个translate 方法。我不知道Word 类与此有什么关系,除了您可能希望将功能移到那里并让translate 使用该类。这个问题太宽泛了,无法进一步回答。
  • Iway ouldway agreeway ithway @eagarmay atthay ethay estionquay isway ootay oadbray。

标签: ruby methods


【解决方案1】:

您的translate 方法不起作用。问题出在这里:

if word[0] == "a" || "e" || "o" || "u" || "i"

elsif word[0] != "a" || "e" || "o" || "u" || "i"

你不能这样比较,因为任何一方的右边都不会像你想象的那样。

一些简单的检查会显示出问题的原因:

'abc'[0] == "a" || "e" || "o" || "u" || "i" # => true
'efg'[0] == "a" || "e" || "o" || "u" || "i" # => "e"
'opq'[0] == "a" || "e" || "o" || "u" || "i" # => "e"
'xyz'[0] == "a" || "e" || "o" || "u" || "i" # => "e"

'abc'[0] != "a" || "e" || "o" || "u" || "i" # => "e"
'efg'[0] != "a" || "e" || "o" || "u" || "i" # => true
'opq'[0] != "a" || "e" || "o" || "u" || "i" # => true
'xyz'[0] != "a" || "e" || "o" || "u" || "i" # => true

为什么错了?让我们看看发生了什么:

当单词以'a'开头时,测试'a' == 'a'为真:

'abc'[0] == "a" # => true

如果我们||(“或”)为真,我们会返回真,因为这是第一个看到的“真”值:

true || "e" # => true

如果第一个测试失败,那么 || 会导致对第二个测试进行评估,在您的代码中是 "e",并且不是测试,但 Ruby 不知道这一点,并认为这是"true" 返回值所以它变成了表达式的结果:

false || "e" # => "e"

知道,正确的写法是:

'abc'[0] == "a" || 'abc'[0] == "e" || 'abc'[0] == "o" || 'abc'[0] == "u" || 'abc'[0] == "i" # => true
'efg'[0] == "a" || 'efg'[0] == "e" || 'efg'[0] == "o" || 'efg'[0] == "u" || 'efg'[0] == "i" # => true
'opq'[0] == "a" || 'opq'[0] == "e" || 'opq'[0] == "o" || 'opq'[0] == "u" || 'opq'[0] == "i" # => true
'xyz'[0] == "a" || 'xyz'[0] == "e" || 'xyz'[0] == "o" || 'xyz'[0] == "u" || 'xyz'[0] == "i" # => false

'abc'[0] != "a" && 'abc'[0] != "e" && 'abc'[0] != "o" && 'abc'[0] != "u" && 'abc'[0] != "i" # => false
'efg'[0] != "a" && 'efg'[0] != "e" && 'efg'[0] != "o" && 'efg'[0] != "u" && 'efg'[0] != "i" # => false
'opq'[0] != "a" && 'opq'[0] != "e" && 'opq'[0] != "o" && 'opq'[0] != "u" && 'opq'[0] != "i" # => false
'xyz'[0] != "a" && 'xyz'[0] != "e" && 'xyz'[0] != "o" && 'xyz'[0] != "u" && 'xyz'[0] != "i" # => true

然而,这很快变得难以阅读和笨拙,所以需要更简洁的东西:

%w[a e o u].include? 'abc'[0] # => true
%w[a e o u].include? 'efg'[0] # => true
%w[a e o u].include? 'opq'[0] # => true
%w[a e o u].include? 'xyz'[0] # => false

!%w[a e o u].include? 'abc'[0] # => false
!%w[a e o u].include? 'efg'[0] # => false
!%w[a e o u].include? 'opq'[0] # => false
!%w[a e o u].include? 'xyz'[0] # => true

这有一个问题;随着数组大小的增加,需要更多循环来与[0] 值进行比较,这会不必要地减慢代码速度。正确编写的正则表达式可以摆脱这种循环,因此速度保持非常恒定:

'abc'[0][/[aeou]/] # => "a"
'efg'[0][/[aeou]/] # => "e"
'opq'[0][/[aeou]/] # => "o"
'xyz'[0][/[aeou]/] # => nil

但请注意,结果不是真/假,而是与模式匹配的字符或 nil。在 Ruby 中,只有 nil 和 false 被认为是 false 值,其他一切都是 true,因此我们可以将它们分别转换为 true、true、true、false,但是通过利用 ! 运算符,我们可以使其更加清晰:

!!'abc'[0][/[aeou]/] # => true
!!'efg'[0][/[aeou]/] # => true
!!'opq'[0][/[aeou]/] # => true
!!'xyz'[0][/[aeou]/] # => false

看起来我们必须使用!!! 来“不”获得使用!= 时想要的结果,但这不是必需的。单个! 会做同样的事情:

!'abc'[0][/[aeou]/] # => false
!'efg'[0][/[aeou]/] # => false
!'opq'[0][/[aeou]/] # => false
!'xyz'[0][/[aeou]/] # => true

但是等等!还有更多!通过删除字符串切片 ([0]) 并使用正则表达式锚点,即使这一点也可以稍微改善。比较这两者及其基准:

require 'fruity'

ALPHABET = ('a'..'z').to_a.join

compare do
  slice_it  { ALPHABET[0][/[aeou]/] }
  regex_it  { ALPHABET[/^[aeou]/] }
end
# >> Running each test 8192 times. Test will take about 1 second.
# >> regex_it is faster than slice_it by 39.99999999999999% ± 10.0%

所以,使用类似的东西:

'abc'[/^[aeou]/]  # => "a"
!'abc'[/^[aeou]/] # => false
!!'abc'[/^[aeou]/]  # => true

将快速而紧凑,让您测试以查看字符串以什么开头。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2018-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多