2017-05-25 31 views
0

我的任務是創建pig_latin方法。如何在Ruby中的方法中實現for循環

Pig Latin is a made-up children's language that's intended to be confusing. It obeys a few simple rules (below) but when it's spoken quickly it's really difficult for non-children (and non-native speakers) to understand.

Rule 1: If a word begins with a vowel sound, add an "ay" sound to the end of the word.

Rule 2: If a word begins with a consonant sound, move it to the end of the word, and then add an "ay" sound to the end of the word.

(There are a few more rules for edge cases, and there are regional variants too, but that should be enough to understand the tests.)

我所有的測試都通過保存一個,來翻譯很多單詞。

這是我的錯誤:

#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 

,但它不是。

+0

'str.each ... return'將返回在第一次迭代的第一個值,所以迭代不會做你想要的。將所有方法嵌入到包裝方法中並不是慣用的。 –

+0

第一次看,讓你的測試通過 - 'str.map {| item | starts_with_consonant(item)|| word_begins_with_vowel(item)} .join('')' –

+0

@AlexGolubenko謝謝朋友!你能否在上下文中添加你的解決方案或顯示你的意思?欣賞它! –

回答

2

由於@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 
+0

UPD;''在行結束是不必要的,也不是慣用的。 'split('')'可以寫成'split',因爲它的默認行爲是在空白處分割。 –

+0

@theTinMan你的權利,但正如我所說的:「以最少的代碼編輯」,在UPD中,你可以看到我的變體) –

+0

而不是使用「UPD」或「更新」或「編輯」,只需添加如果你最初將它包含在內,那麼它會消失的信息。 SO維護對所有問題和答案的修訂控制,因此我們可以看到發生了什麼變化以及何時需要。清晰度和可讀性比每週註釋和改變更重要。 –