这个功能如何运作?

时间:2014-01-09 23:35:13

标签: ruby

ordered_vowel_words方法和ordered_vowel_word?辅助方法接受一个单词,如果单词的元音顺序为(a,e,i,o,u),则返回单词。

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

有人可以解释一下这是如何运作的吗?我不明白all?是如何调用range的。

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

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

all?块基本上是在vowels_arr数组上进行迭代,将每个值与下一个值进行比较。如果所有比较都返回true,那么all?也将返回true,这意味着数组已被排序。如果其中一个迭代返回false,则all?的返回值也将为false,这意味着该集合是无序的。

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

您可以通过在irb中尝试以下内容来验证这一点:

Range.included_modules # => => [Enumerable, Kernel]

答案 2 :(得分:0)

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

答案 3 :(得分:0)

这是我解决这个问题的方法:

def ordered_vowel_words(str)
  vowels_s = str.scan(/[aeiou]/)
  vowels_sort = str.scan(/[aeiou]/).sort
  vowels_s === vowels_sort ? str : ""
end