【问题标题】:How does "each" function work in Ruby (and therefor Rails)?“每个”函数在 Ruby(以及 Rails)中是如何工作的?
【发布时间】:2011-09-25 01:54:16
【问题描述】:

在我正在阅读的学习 Rails (RailsS​​pace) 的书中,作者创建了两个函数(如下)将所有大写城市名称(如 LOS ANGELES)转换为 Los Angeles。然而,下面的第一个函数有一些我不明白的地方。

即,“词”从何而来?我知道“word”是一个局部/块变量,在函数完成后消失,但是什么被传递/分配给“word”。换句话说,什么是分裂?

我原以为会有某种参数将数组或哈希传递给这个函数......然后“每个”函数运行在它上面......

def capitalize_each
  space = " "
  split(space).each{ |word| word.capitalize! }.join(space)     
end   

# Capitalize each word in place.     
def capitalize_each!
  replace capitalize_each end
end

【问题讨论】:

  • 这不是 Ruby 的惯用用法。如果你想把一个数组变成另一个数组,最好使用map而不是each,像这样:words.map{|word|word.capitalize}.join(' ')。 (没有尾随的!capitalize 生成一个新字符串而不是修改旧字符串,map 将这些新字符串收集到一个新数组中。)

标签: ruby string


【解决方案1】:

让我们分手吧。

split(space)

将字符串转换为可能的单词列表。 (实际上,如果字符串连续有两个空格,则列表中将有一个空字符串。但这对于此目的无关紧要。)我假设这是String 中的实例方法;否则,split 将不会被定义。

.each { |word| word.capitalize! }

.each 获取列表中的每个事物(由 split 返回),并在其上运行以下块,将事物作为 arg 传递给该块。 |word| 表示此块将调用 arg“单词”。如此有效,它所做的就是将字符串中的每个单词大写(以及每个空白字符串和单独的标点符号,但同样,这并不重要——大写不会改变没有大小写概念的字符)。

.join(space)

将单词重新粘合在一起,重新插入之前用于分隔它们的空间。它返回的字符串也是函数的返回值。

【讨论】:

    【解决方案2】:

    起初我认为该方法不完整,因为开头没有self,但似乎即使没有它,split 也会在给定的字符串上被调用,space 只是一个默认分隔符.这就是该方法在显式 self 下的外观。

    class String
        def capitalize_each(separator = ' ')
            self.split(separator).each{|word| word.capitalize!}.join(separator)
        end
    end
    
    puts "LOS ANGELES".capitalize_each #=> Los Angeles
    puts "LOS_ANGELES".capitalize_each('_') #=> Los_Angeles
    

    【讨论】:

    • self 是隐含的,除非它是模棱两可的(即在调用 writer 方法时)。
    • 谢谢,以前不知道,但是当我尝试示例并按预期工作时猜到了。
    【解决方案3】:

    字符串被空格分割,即分成单词。 因此,“每个”迭代器每次都在“单词”对象中时逐个遍历所有单词。因此,对于该对象(单词),它使用大写函数。最后,这一切都与 Spaces 重新结合在一起。所以最终结果是大写的。

    【讨论】:

      【解决方案4】:

      这些方法是在 String 类中定义的,所以要拆分的是您调用 capitalize_each 方法的任何字符串。

      一些示例用法(以及更好的实现):

      class String
        def capitalize_each
          split(/\s+/).each{ |word| word.capitalize! }.join " " 
        end
      
        def capitalize_each!
          replace capitalize_each
        end
      end
      
      puts "hi, i'm a sentence".capitalize_each #=> Hi, I'm A Sentence
      

      【讨论】:

      • 除非"Hi, i'm a string that intentionally has a bunch of spaces" 变成了错误的东西。如果我不想要额外的空间,我会删除它们。不要为我弄乱我的弦,kthx。 :)
      • 呸。不能做这个该死的例子,因为 Markdown 似乎是一起 smooshing 空间。
      • 这个想法是处理字符串包含制表符或换行符的情况。也许像"Hi,\t i'm a \tstring".gsub(/\s+\w/) { |s| s.upcase } 这样的东西是理想的。
      【解决方案5】:

      |word| word.capitalize! 视为您传递给each 方法的函数。该函数有一个参数 (word) 并简单地计算 .capitalize!

      现在each 方法正在做的是获取split(space) 中的每个项目并在其上评估您的函数。所以:

      "abcd".each{|x| print x}
      

      将依次评估print "a"print "b"print "c"

      http://www.ruby-doc.org/core/classes/Array.html#M000231

      为了稍微揭开这种行为的神秘面纱,它有助于准确理解“获取 __ 中的每个项目”的含义。基本上,任何enumerable 的对象都可以通过这种方式被.eached。

      【讨论】:

        【解决方案6】:

        如果您首先指的是它是如何进入您的区块的,那么它就会进入区块。 #split 返回一个数组,它的 #each 方法正在执行以下操作:

        for object in stored_objects
          yield object
        end
        

        【讨论】:

          【解决方案7】:

          这可行,但如果你想将一个数组转换为另一个数组,习惯上最好使用map 而不是each,如下所示:

          words.map{|word|word.capitalize}
          

          (没有尾随的!capitalize 生成一个新字符串而不是修改旧字符串,map 将这些新字符串收集到一个新数组中。相比之下,each 返回旧数组。)

          或者,跟随古恩的领导:

          class String
            def capitalize_each
              self.split(/\s/).map{|word|word.capitalize}.join(' ')
            end
          end
          
          "foo bar  baz".capitalize_each #=> "Foo Bar  Baz"
          

          默认情况下,splitstrings 个空格上进行分割,但通过传递正则表达式,它匹配每个 individual 个空格字符,即使它们在一行中。

          【讨论】:

            猜你喜欢
            • 2011-05-08
            • 1970-01-01
            • 1970-01-01
            • 2011-09-27
            • 2022-11-16
            • 2014-10-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多