2014-01-09 84 views
0

ordered_vowel_words方法和ordered_vowel_word?辅助方法接受一个单词并返回单词,如果单词的元音符合(a,e,i,o,u)的顺序。这个功能是如何工作的?

我无法理解逻辑。特别是帮助方法中的最后一个块(0...(vowels_arr.length - 1)).all? do...如何工作。

有人可以解释这是如何工作的?我不明白如何在range上调用all?

def ordered_vowel_words(str) 
    words = str.split(" ") 

    ordered_vowel_words = words.select do |word| 
    ordered_vowel_word?(word) 
    end 

    ordered_vowel_words.join(" ") 
end 

def ordered_vowel_word?(word) 
    vowels = ["a", "e", "i", "o", "u"] 

    letters_arr = word.split("") 
    vowels_arr = letters_arr.select { |l| vowels.include?(l) } 

    (0...(vowels_arr.length - 1)).all? do |i| 
    vowels_arr[i] <= vowels_arr[i + 1] 
    end 
end 
+0

http://ruby-doc.org/core-2.1.0/Enumerable.html – Beartech

回答

1

我添加了一些意见:)

def ordered_vowel_words(str) 
    # words is a string with words separated by a whitespace. 
    # split generates an array of words from a string 
    words = str.split(" ") 

    # select only the ordered vowel words from the previous array 
    ordered_vowel_words = words.select do |word| 
    ordered_vowel_word?(word) 
    end 

    # join the ordered vowel words in a single string 
    ordered_vowel_words.join(" ") 
end 

def ordered_vowel_word?(word) 
    # THESE ARE THE VOWELS YOU FOOL 
    vowels = ["a", "e", "i", "o", "u"] 

    # transform the word in an array of characters 
    letters_arr = word.split("") 

    # select only the vowels in this array 
    vowels_arr = letters_arr.select { |l| vowels.include?(l) } 

    # generate a range from 0 to the length of the vowels array minus 2: 
    # there is this weird range because we want to iterate from the first vowel 
    # to the second to last; all? when called on a range returns true if... 
    (0...(vowels_arr.length - 1)).all? do |i| 
    # for each number in the range, the current vowel is smaller that the next vowel 
    vowels_arr[i] <= vowels_arr[i + 1] 
    end 
end 

希望这有助于!

编辑我可能会补充说,最后一块并不觉得Ruby-ish。我建议这个替代实现:

def ordered_vowel_word?(word) 
    vowels = ["a", "e", "i", "o", "u"] 

    # transform the word in an array of characters 
    letters_arr = word.split("") 

    # select only the vowels in this array 
    vowels_arr = letters_arr.select { |l| vowels.include?(l) } 

    # from this array generate each possible consecutive couple of characters 
    vowels_arr.each_cons(2).all? do |first, second| 
    first <= second 
    end 
end 

require 'rspec/autorun' 

describe "#ordered_vowel_word?" do 
    it "tells if word is ordered" do 
    expect(ordered_vowel_word?("aero")).to be_true 
    end 

    it "or not" do 
    expect(ordered_vowel_word?("rolling")).to be_false 
    end 
end 
+0

谢谢“FOOL!” :) - 你的评论帮助我意识到了一些事情。我跳入'irb',并尝试了''一个“<”e“',我回到了'真实'。我忘了那个。现在我明白'(0 ...(vowels_arr.length - 1))。all?做|我| vowels_arr [i] <= vowels_arr [i + 1]'正在做。我无法确定它是如何确定订单是否正确的。那么现在我意识到了 fyz

+0

我已经添加了更多的Ruby-ish实现,并通过了测试:) Ciao bello! –

+0

另一种方法是令人愉快的。非常好!谢谢,再见! – fyz

0

all?块基本上遍历vowels_arr阵列,比较每个值与它的下一个。如果所有的比较返回true那么all?也将返回true,这意味着数组是有序的。如果其中一个迭代返回false,返回值all?也将是false,这意味着该集合是无序的。

您可以在Rangehttp呼吁all?://www.ruby-doc.org/core-1.9.3/Range.html对象,因为Range混合在Enumerablehttp://www.ruby-doc.org/core -1.9.3/Enumerable.html模块,它定义了all?

您可以尝试在IRB以下验证这一点:

Range.included_modules # => => [Enumerable, Kernel] 
0
  1. 第一部分(0...(vowels_arr.length - 1))创造多少元音在词的范围 0。
  2. all?在该范围内迭代并返回true如果全部为 范围元素的某些条件为真否则为false。
  3. do |i|引入了i作为表示 步骤1中创建
  4. 最后的范围内的每个元素,条件是在范围内的每个索引变量的块,现在由i表示的,它会检查是否vowels_arr[i] <= vowels_arr[i+1]为真。