Преобразование верблюжьего футляра в подчеркивание в рубине


232

Есть ли какая-либо готовая функция, которая преобразует строки с верблюжьими символами в строку, разделенную подчеркиванием?

Я хочу что-то вроде этого:

"CamelCaseString".to_underscore      

вернуть "camel_case_string".

...


43
К вашему сведению: строчные и подчеркнутые буквы «официально» называются «змеиными»
Эндрю

3
Странно видеть «официально» в кавычках, и все же, это лучший способ описать это.
Стивеншпиль

Почему-то я вижу, что метод snakecase отсутствует. Рельсы 4.
Абрам

Ответы:


363

ActiveSupport от Rails добавляет подчеркивание к строке, используя следующее:

class String
  def underscore
    self.gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr("-", "_").
    downcase
  end
end

Тогда вы можете делать забавные вещи:

"CamelCase".underscore
=> "camel_case"

5
Если вы измените tr("-","_")на tr("- ","_")(пробел добавлен к первому параметру), это также превратит пробелы в подчеркивания. Кроме того, я не думаю, что вам даже нужно включать self., или, по крайней мере, это работает для меня под Ruby 1.9.3.
Гас Шортц

6
require 'active_support/core_ext/string'
konsolebox

Подчеркивание функция Активные применения: github.com/rails/rails/blob/...
GreeKatrina

подчеркивание - это метод Rails, а не ruby, см. apidock.com/rails/String/underscore .
С.Ядав

1
@ S.Yadav true метод является Rails, поэтому вы не можете вызывать подчеркивание по умолчанию, но, предоставив код и указав rails в качестве источника, этот ответ подходит для ruby, он говорит, что вы можете включить rails или просто включите эту функцию, которую команда разработчиков рельсов написала и проверила.
Майкл Горман

99

Ты можешь использовать

"CamelCasedName".tableize.singularize

Или просто

"CamelCasedName".underscore

Оба варианта пути дадут "camel_cased_name". Вы можете проверить более подробную информацию здесь .


11
Это часть реализации ActiveSupport :: Inflector, без которой вы не можете использовать эти расширения String (попробуйте в чистой консоли irb: «ThisCamelCaseString» .underscore, затем потребуйте «active_support / inflector» и повторите попытку)
Евгения Манолова

3
На этикетке OP написано "ruby-on-rails"
Жюльен Ламарш

55

Однострочная реализация Ruby:

class String
   # ruby mutation methods have the expectation to return self if a mutation occurred, nil otherwise. (see http://www.ruby-doc.org/core-1.9.3/String.html#method-i-gsub-21)
   def to_underscore!
     gsub!(/(.)([A-Z])/,'\1_\2')
     downcase!
   end

   def to_underscore
     dup.tap { |s| s.to_underscore! }
   end
end

Так "SomeCamelCase".to_underscore # =>"some_camel_case"


2
как другие решения не являются чистым рубином?
jrhicks

О, боже ... Спасибо - меня больше интересовало письмо, чем чтение. В результате ссылки на Rails заставили меня думать, что эти другие фрагменты относятся к Rails. Измененный ответ ...
kirushik

1
в моей правке есть еще одна ошибка, и я не могу ее исправить. Вот исправленный код: gist.github.com/4027440
Тим Харпер

6
Вы можете рассмотреть /([^A-Z])([A-Z]+)/вместо этого, чтобы обработать "ALLCAPS"-> "allcaps"вместо"a_ll_ca_ps"
Невир

4
Это на самом деле 10-лайнер!
Кристианп

30

Существует встроенный метод Rails, который называется underscore и который вы можете использовать для этой цели.

"CamelCaseString".underscore #=> "camel_case_string" 

Метод «подчеркивания» обычно можно рассматривать как инверсию «верблюда»


1
undefined метод `underscore 'для" ... ": String
Dorian

5
Это метод ActiveSupport
Дориан

20

Вот как это делает Rails :

   def underscore(camel_cased_word)
     camel_cased_word.to_s.gsub(/::/, '/').
       gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
       gsub(/([a-z\d])([A-Z])/,'\1_\2').
       tr("-", "_").
       downcase
   end

1
Лучше иметь операнд в качестве аргумента метода, чем вторгаться в основной класс String.
Pistos

1
Не соглашайтесь - лучше, чтобы он работал с классом так, как он должен быть, иначе вы должны будете вставить его в модуль и не забудьте включить его там, где он вам понадобится.
Готи

1
Также этот метод является частью строк Rails 3 в любом случае :)
Ghoti

2
Если я могу перейти к этой дискуссии - лучше, чтобы она вторглась в класс строк, когда вы включите его =).
Эван Моран

7

Приемник преобразован в корпус змеи: http://rubydoc.info/gems/extlib/0.9.15/String#snake_case-instance_method

Это библиотека поддержки для DataMapper и Merb. ( http://rubygems.org/gems/extlib )

def snake_case
  return downcase if match(/\A[A-Z]+\z/)
  gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
  gsub(/([a-z])([A-Z])/, '\1_\2').
  downcase
end

"FooBar".snake_case           #=> "foo_bar"
"HeadlineCNNNews".snake_case  #=> "headline_cnn_news"
"CNN".snake_case              #=> "cnn"

7

Проверьте змею от Ruby Facets

Следующие случаи обрабатываются, как показано ниже:

"SnakeCase".snakecase         #=> "snake_case"
"Snake-Case".snakecase        #=> "snake_case"
"Snake Case".snakecase        #=> "snake_case"
"Snake  -  Case".snakecase    #=> "snake_case"

От: https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/snakecase.rb

class String

  # Underscore a string such that camelcase, dashes and spaces are
  # replaced by underscores. This is the reverse of {#camelcase},
  # albeit not an exact inverse.
  #
  #   "SnakeCase".snakecase         #=> "snake_case"
  #   "Snake-Case".snakecase        #=> "snake_case"
  #   "Snake Case".snakecase        #=> "snake_case"
  #   "Snake  -  Case".snakecase    #=> "snake_case"
  #
  # Note, this method no longer converts `::` to `/`, in that case
  # use the {#pathize} method instead.

  def snakecase
    #gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr('-', '_').
    gsub(/\s/, '_').
    gsub(/__+/, '_').
    downcase
  end

  #
  alias_method :underscore, :snakecase

  # TODO: Add *separators to #snakecase, like camelcase.

end

Он не работает со строкой со специальным символом. Пример:"Dumb Penguin's Egg".snakecase # => "dumb_penguin's_egg"
Khiav Reoy

6

Короткий oneliner для CamelCases, когда у вас также есть пробелы (не работает правильно, если у вас есть слово между маленькими начальными буквами):

a = "Test String"
a.gsub(' ', '').underscore

  => "test_string"

1
underscoreне является частью ruby
dft

5

В случае, если кто-то ищет случай, когда ему нужно применить подчеркивание к строке с пробелами, и вы хотите также преобразовать их в подчеркивание, вы можете использовать что-то вроде этого

'your String will be converted To underscore'.parameterize.underscore
#your_string_will_be_converted_to_underscore

Или просто используйте .parameterize ('_'), но имейте в виду, что этот не рекомендуется

'your String will be converted To underscore'.parameterize('_')
#your_string_will_be_converted_to_underscore

1

Я хотел бы это:

class String

  # \n returns the capture group of "n" index
  def snikize
    self.gsub(/::/, '/')
    .gsub(/([a-z\d])([A-Z])/, "\1_\2")
    .downcase
  end

  # or

  def snikize
    self.gsub(/::/, '/')
    .gsub(/([a-z\d])([A-Z])/) do
      "#{$1}_#{$2}"
    end
    .downcase
  end

end

Обезьянья нашивка Stringкласса. Есть класс, который начинается с двух или более букв в верхнем регистре.


Вам нужно изменить , "\1_\2"чтобы в '\1_\2'противном случае вы будете в конечном итоге с "came\u0001_\u0002ase"вместо , "camel_case"как Руби 2.5 ... может быть , другие , а также.
футов Дан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.