【问题标题】:How to implement a for loop in a method in Ruby如何在 Ruby 中的方法中实现 for 循环
【发布时间】:2017-05-25 21:08:43
【问题描述】:

我的任务是创建一个pig_latin 方法。

猪拉丁语是一种虚构的儿童语言,旨在成为 令人困惑。它遵守一些简单的规则(如下),但是当它被说出来时 很快,对于非儿童(和非本地人)来说真的很难 演讲者)来理解。

规则 1:如果单词以元音开头,则添加“ay” 词尾。

规则 2:如果单词以辅音开头,则将其移至末尾 词尾,然后在词尾加上“ay”音。

(对于边缘情况还有一些规则,并且有区域性 变体也是如此,但这应该足以理解测试。)

我所有的测试都通过了保存一个,翻译很多单词。

这是我的错误:

#translate
  translates a word beginning with a vowel
  translates a word beginning with a consonant
  translates a word beginning with two consonants
  translates two words
  translates a word beginning with three consonants
  counts 'sch' as a single phoneme
  counts 'qu' as a single phoneme
  counts 'qu' as a consonant even when it's preceded by a consonant
  translates many words (FAILED - 1)

Failures:

  1) #translate translates many words
     Failure/Error: expect(s).to eq("ethay ickquay ownbray oxfay")

       expected: "ethay ickquay ownbray oxfay"
            got: "ethay"

       (compared using ==)
     # ./spec/04_pig_latin_spec.rb:70:in `block (2 levels) in <top (required)>'

Finished in 0.00236 seconds (files took 0.10848 seconds to load)
9 examples, 1 failure

Failed examples:

rspec ./spec/04_pig_latin_spec.rb:68 # #translate translates many words

这是我的方法:

def translate(str)

  def add_ay(str)
   return str + 'ay'
  end

  def word_begins_with_vowel(str)
    if (!(str.match(' '))) && $vowels[str[0]]
      return add_ay(str)
    end     
  end

  def begins_with_consonant(str)
    if ((!$vowels[str[0]]) && (!$vowels[str[1]]) && (!$vowels[str[2]])) 
      first_three = str.split('').slice(0, 3).join('');
      str = str.slice(3, str.length - 1)
      return str +  first_three + 'ay'
    end
    if ((!$vowels[str[0]]) && (!$vowels[str[1]])) 
      first_two = str.split('').slice(0, 2).join('');
      str = str.slice(2, str.length - 1)
      return str +  first_two + 'ay'
    end
    if ((!$vowels[str[0]]))
     first_char = str.split('').slice(0);
     str = str.slice(1, str.length - 1)
     return str + first_char +'ay'
    end
  end

  def translates_two_words(str)
    if (str.match(' '))
      str = str.split(' ');
      first_char = str[1].split('').slice(0);
      str[1] = str[1].slice!(1, str[1].length - 1);

      return str[0] + 'ay' + ' ' + str[1] + first_char + 'ay'
    end     
  end

  def translates_many_words(str)
      str = str.split(' ');
      if str.length > 2
        str.each do |item| 
          return begins_with_consonant(item) || word_begins_with_vowel(item)
        end
      end
  end

  $vowels = {
    'a' => add_ay(str),
    'e' => add_ay(str), 
    'i' => add_ay(str), 
    'o' => add_ay(str), 
    'y' => add_ay(str)
  }
    return translates_many_words(str) || word_begins_with_vowel(str) || begins_with_consonant(str) || translates_two_words(str)
end

我认为这会处理很多单词:

def translates_many_words(str)
      str = str.split(' ');
      if str.length > 2
        str.each do |item| 
          return begins_with_consonant(item) || word_begins_with_vowel(item)
        end
      end
  end

但事实并非如此。

【问题讨论】:

  • str.each... return 将在第一次迭代中返回第一个值,因此迭代不会做你想要的。将所有方法都嵌入到包装方法中并不习惯。
  • 第一眼,让您的测试通过 - str.map { |item| begins_with_consonant(item) || word_begins_with_vowel(item) }.join(' ')
  • @AlexGolubenko 谢谢朋友!您能否在上下文中添加您的解决方案或显示您的意思?欣赏!
  • @AntonioPavicevac-Ortiz 我建议你检查我的答案的 UPD

标签: ruby


【解决方案1】:

正如@theTinMan 所说,return - 将拒绝下一次迭代并只返回第一次迭代中的第一个值,从我的评论来看,我认为这对你有用(只需对你的代码进行最少的编辑):

def translates_many_words(str)
  str = str.split(' ');

  if str.length > 2
    str.map do |item| 
      begins_with_consonant(item) || word_begins_with_vowel(item)
    end.join(' ')
  end
end

UPD 另外,我建议您重构代码以使其更具可读性,它可以在将来帮助您。 我的这种方法的变体是:

def translates_many_words(str)
  str = str.split

  # line under - is a shortcut from `return nil if str.size <= 2`
  # `#size` is more relative to this context if you will count elements of array 
  return unless str.size > 2 

  # Now, when we excluded possibility of work with array that have less then 2 elements, 
  # we can continue with our iteration
  str.map do |item| 
    begins_with_consonant(item) || word_begins_with_vowel(item)
  end.join(' ')
end

【讨论】:

  • ; 在行尾不是必需的,也不是惯用的。 split(' ') 可以写成split,因为它的默认行为是在空格上分割。
  • @theTinMan 你的权利,但是,正如我所说:“在 UPD 中,你可以看到我的变体”
  • 不要使用“UPD”或“update”或“edit”,只需将信息添加到原本包含的位置即可。 SO 保持对所有问题和答案的修订控制,因此我们可以看到发生了什么变化以及何时需要。清晰和可读性比每周记录和更改更重要。
猜你喜欢
  • 2014-02-15
  • 2011-08-11
  • 2021-08-10
  • 2017-02-11
  • 2021-10-28
  • 2012-04-16
  • 2021-09-26
  • 2019-11-15
  • 1970-01-01
相关资源
最近更新 更多