【问题标题】:Converting string from snake_case to CamelCase in Ruby在Ruby中将字符串从snake_case转换为CamelCase
【发布时间】:2012-03-20 10:25:39
【问题描述】:

我正在尝试将名称从蛇案例转换为骆驼案例。有没有内置方法?

例如:"app_user""AppUser"

(我有一个字符串"app_user" 我想将其转换为模型AppUser)。

【问题讨论】:

标签: ruby-on-rails ruby string


【解决方案1】:

如果您使用的是 Rails,String#camelize 就是您要找的。​​p>

  "active_record".camelize                # => "ActiveRecord"
  "active_record".camelize(:lower)        # => "activeRecord"

如果你想获得一个真正的课程,你应该在上面使用String#constantize

"app_user".camelize.constantize

【讨论】:

  • 你应该补充一点,这是 Rails 对 String 的补充,它不适用于纯 Ruby。
  • 它被标记为ruby-on-rails,所以,我想,这不是问题。不过谢谢你的提及。
  • 在常量化之前不需要驼峰化。请改用#classify"some_namespace/module/class_name".classify => "SomeNamespace::Module::ClassName"
  • @chris #classify:不一样。 #classify 返回一个字符串,而 #constantize 在上下文中查找常量(并且确实需要 camelize)。 'active_record'.constantize 给出错误,'active_record'.camelize.constantize 返回常量 ActiveRecord,'active_record'.classify 返回字符串 'ActiveRecord'。如果你做了 'no_class'.camelize.constantize 你会得到错误(没有这样的常量 NoClass),但 'no_class'.classify 很高兴返回 'NoClass' 字符串。
  • 为了在纯 Ruby 中使用 Rails 的这些方法,require "active_support/core_ext/string" 就足够了,前提是已经安装了 Rails。
【解决方案2】:

这个怎么样?

"hello_world".split('_').collect(&:capitalize).join #=> "HelloWorld"

在这里的 cmets 中找到:Classify a Ruby string

查看Wayne Conrad的评论

【讨论】:

  • 你太棒了,谢谢。我不想仅仅为了这么小的任务而包含 Rails 库。这很漂亮。 :)
  • 这是对这个问题的唯一真正答案之一。不使用 Rails 库。
【解决方案3】:

如果您使用 Rails,请使用 classify。它可以很好地处理边缘情况。

"app_user".classify # => AppUser
"user_links".classify   # => UserLink

注意:

此答案特定于问题中给出的描述(不是特定于问题标题)。如果有人试图将字符串转换为驼峰式,他们应该使用Sergio 的答案。提问者说他​​想将app_user 转换为AppUser(不是App_user),因此这个答案..

【讨论】:

  • 对于 Rails 环境,这是完美的。
  • 注意classify返回的是一个字符串,之后你必须调用constantize才能将它转换为一个实际的类。
  • classify 的一个重要警告是复数字符串将变为单数...'age_in_years'.classify 变为 AgeInYear
  • @br3nt 它没有复数,因为 activerecord 4.2.11
【解决方案4】:

来源:http://rubydoc.info/gems/extlib/0.9.15/String#camel_case-instance_method

出于学习目的:

class String
  def camel_case
    return self if self !~ /_/ && self =~ /[A-Z]+.*/
    split('_').map{|e| e.capitalize}.join
  end
end

"foo_bar".camel_case          #=> "FooBar"

对于小写变体:

class String
  def camel_case_lower
    self.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
  end
end

"foo_bar".camel_case_lower          #=> "fooBar"

【讨论】:

  • @pguardiario 如果轮子被称为 ActiveSupport,请重新发明它。
  • 我认为小写变体是错误的。注入块不应直接操作缓冲区,而是返回缓冲区的新值:self.split('_').inject([]){ |buffer,e| buffer + [buffer.empty? ? e : e.capitalize] }.join
【解决方案5】:

纯 Ruby 解决方案的基准

我想到了用纯 ruby​​ 代码来做这件事的所有可能性,它们是:

  • 大写和 gsub

    'app_user'.capitalize.gsub(/_(\w)/){$1.upcase}
    
  • 使用&速记进行拆分和映射(感谢user3869936的回答)

    'app_user'.split('_').map(&:capitalize).join
    
  • 拆分和映射(感谢布莱克先生的回答)

    'app_user'.split('_').map{|e| e.capitalize}.join
    

这里是所有这些的基准,我们可以看到 gsub 对此非常不利。我用了 126 080 个字。

                              user     system      total        real
capitalize and gsub  :      0.360000   0.000000   0.360000 (  0.357472)
split and map, with &:      0.190000   0.000000   0.190000 (  0.189493)
split and map        :      0.170000   0.000000   0.170000 (  0.171859)

【讨论】:

    【解决方案6】:

    我来这里是为了寻找与您的问题相反的问题,从骆驼案到蛇案。使用underscore (不是decamelize):

    AppUser.name.underscore # => "app_user"

    或者,如果您已经有驼峰式字符串:

    "AppUser".underscore # => "app_user"

    或者,如果您想获取表名,这可能就是您想要蛇形案例的原因:

    AppUser.name.tableize # => "app_users"

    【讨论】:

    • 为什么不使用AppUser.table_name?如果不是 app_users 而是在别处定义的名称,您还将确保拥有真实的表名。
    【解决方案7】:

    我觉得在这里添加更多答案有点不安。决定采用最易读和最小化的纯 ruby​​ 方法,无视 @ulysse-bn 的良好基准。虽然:class 模式是@user3869936 的副本,但:method 模式我在这里的任何其他答案中都看不到。

      def snake_to_camel_case(str, mode: :class)
        case mode
        when :class
          str.split('_').map(&:capitalize).join
        when :method
          str.split('_').inject { |m, p| m + p.capitalize }
        else
          raise "unknown mode #{mode.inspect}"
        end
      end
    

    结果是:

    [28] pry(main)> snake_to_camel_case("asd_dsa_fds", mode: :class)
    => "AsdDsaFds"
    [29] pry(main)> snake_to_camel_case("asd_dsa_fds", mode: :method)
    => "asdDsaFds"
    

    【讨论】:

    • 驼峰式的情况实际上首先要低一些。否则,它被命名为 PascalCase(或有时是大写驼峰式)。即使在这个问题中它是模棱两可的!
    • @UlysseBN,tbh 我不喜欢这些词的历史。维基百科声称PascalCaseCamelCase 的子集。这也是我所知道的——骆驼案适用于两者。但我从来没有调查过。感谢您提到 PascalCase。 en.wikipedia.org/wiki/Camel_case
    • 这是 imo 页面上的最佳答案。如果:method 版本首先执行downcase 那就太好了,这样它就可以在lower_snake_caseUPPER_SNAKE_CASE 上使用。
    【解决方案8】:

    ruby 核心本身不支持将字符串从蛇大小写转换为(大)驼峰大小写(也称为帕斯卡大小写)。

    因此,您需要自己实现或使用现有的 gem。

    有一个名为 lucky_case 的小型 ruby​​ gem,它允许您轻松地将字符串从 10 多种支持的情况转换为另一种情况:

    require 'lucky_case'
    
    # to get upper camel case (pascal case) as string
    LuckyCase.pascal_case('app_user') # => 'AppUser'
    # to get the pascal case constant
    LuckyCase.constantize('app_user') # => AppUser
    # or the opposite way
    LuckyCase.snake_case('AppUser')   # => app_user
    

    如果你愿意,你甚至可以修改 String 类:

    require 'lucky_case/string'
    
    'app_user'.pascal_case # => 'AppUser'
    'app_user'.constantize # => AppUser
    # ...
    

    查看官方存储库以获取更多示例和文档:

    https://github.com/magynhard/lucky_case

    【讨论】:

      【解决方案9】:

      扩展字符串以添加 Camelize

      在纯 Ruby 中,您可以使用从 Rails .camelize 提取的代码扩展字符串类

      class String
        def camelize(uppercase_first_letter = true)
          string = self
          if uppercase_first_letter
            string = string.sub(/^[a-z\d]*/) { |match| match.capitalize }
          else
            string = string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { |match| match.downcase }
          end
          string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }.gsub("/", "::")
        end
      end
      

      【讨论】:

        【解决方案10】:

        这里列出的大多数其他方法都是特定于 Rails 的。如果你想用纯 Ruby 做到这一点,以下是我想出的最简洁的方法(感谢 @ulysse-bn 提出的改进建议)

        x="this_should_be_camel_case"
        x.gsub(/(?:_|^)(\w)/){$1.upcase}
            #=> "ThisShouldBeCamelCase"
        

        【讨论】:

        • 你对“骆驼案”的定义太有限了。例如,Java 和 Ruby 中的类名 驼峰式 MyFavoriteClass...,但它们也没有小写首字母。有时骆驼案有初始上限。有时不会。
        • 在只能使用一个的地方使用 2 个正则表达式是矫枉过正的。您只能使用非捕获组:x.gsub(/(?:_|^)(\w)/){$1.upcase}
        • @UlysseBN,我们又回到了您的gsub 解决方案,与map 解决方案相比,它似乎更慢。
        • 这并不复杂:camelCase 的第一个字符是小写的。 PascalCase 有一个大写的第一个字符。我责怪 Rails 有一个默认返回 PascalCase 的驼峰式方法。 apidock.com/rails/String/camelize
        • 虽然您在技术上或历史上可能是正确的 Darren,但社区并没有做出这种区分。例如,Java 类名的首字母大写,并且在几乎每一篇提到它的文章/帖子中,该约定都称为“驼峰式”,即使是早在 Rails 之前编写的那些。较低的首字母基本上在任何地方也被描述为“驼峰式”。两者都是现代定义的“骆驼案”。
        猜你喜欢
        • 2012-02-01
        • 1970-01-01
        • 2017-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-25
        • 2019-05-21
        相关资源
        最近更新 更多