रूबी में snake_case से CamelCase में स्ट्रिंग परिवर्तित करना


171

मैं एक नाम को सांप के मामले से ऊंट मामले में बदलने की कोशिश कर रहा हूं। क्या कोई अंतर्निहित तरीके हैं?

जैसे: "app_user"को"AppUser"

(मेरे पास एक स्ट्रिंग है जिसे "app_user"मैं मॉडल में बदलना चाहता हूं AppUser)।

जवाबों:


251

यदि आप रेल का उपयोग कर रहे हैं, तो स्ट्रिंग # कैमलाइज़ करें जो आप खोज रहे हैं।

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

यदि आप एक वास्तविक वर्ग प्राप्त करना चाहते हैं, तो आपको उसके शीर्ष पर स्ट्रिंग # स्थिरांक का उपयोग करना चाहिए ।

"app_user".camelize.constantize

44
आपको जोड़ना चाहिए कि यह स्ट्रिंग के अलावा एक रेल है, यह शुद्ध रूबी के साथ काम नहीं करता है।
आईजीएल

2
यह टैग किया गया है ruby-on-rails, इसलिए, मुझे लगता है, यह कोई समस्या नहीं है। लेकिन उल्लेख करने के लिए धन्यवाद।
सर्जियो तुलेंत्सेव

6
आपको निरंतरता से पहले व्यवस्थित करने की आवश्यकता नहीं है। #classifyइसके बजाय उपयोग करें । "some_namespace/module/class_name".classify => "SomeNamespace::Module::ClassName"
क्रिस हेडल

5
@chris #classify: यही नहीं। #classify एक स्ट्रिंग देता है, जबकि #constantize संदर्भ में निरंतर दिखता है (और ऊंट की जरूरत है)। 'active_record'.constantize त्रुटि देता है,' active_record'.camelize.constantize स्थिर ActiveRecord लौटाता है, 'active_record'.classify रिटर्न' स्ट्रिंग 'ActiveRecord'। और अगर आपने 'no_class'.camelize.constantize किया तो आपको त्रुटि (ऐसी कोई स्थिर NoClass) नहीं मिलेगी, लेकिन' no_class'.classify खुशी से 'NoClass' स्ट्रिंग देता है।
कनात बोलज़ार

शुद्ध रूबी से रेल के इन तरीकों का उपयोग करने के लिए, require "active_support/core_ext/string"पर्याप्त है, बशर्ते रेल पहले से ही स्थापित हो।
मसा सकानो

120

इसके बारे में क्या खयाल है?

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

यहाँ टिप्पणियों में मिला: रूबी स्ट्रिंग वर्गीकृत करें

वेन कॉनराड की टिप्पणी देखें


10
आप कमाल के हैं, शुक्रिया। मैं इस छोटे से काम के लिए रेल पुस्तकालयों को शामिल नहीं करना चाहता था। ये सुन्दर है। :)
गेरी

11
यह प्रश्न के एकमात्र वास्तविक उत्तर में से एक है। रेल पुस्तकालयों का उपयोग नहीं करना।
लुइस ओर्टेगा अरानेडा

40

यदि आप रेल का उपयोग करते हैं, तो उपयोग करें classify। यह किनारे के मामलों को अच्छी तरह से संभालता है।

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

ध्यान दें:

यह उत्तर प्रश्न में दिए गए विवरण के लिए विशिष्ट है (यह प्रश्न शीर्षक के लिए विशिष्ट नहीं है)। यदि कोई ऊंट-मामले में एक स्ट्रिंग को बदलने की कोशिश कर रहा है, तो उन्हें सर्जियो के उत्तर का उपयोग करना चाहिए । प्रश्नकर्ता राज्यों वह परिवर्तित करने के लिए चाहता है कि app_userकरने के लिए AppUser(नहीं App_user), इसलिए इस जवाब ..


4
रेल वातावरण के लिए, यह एकदम सही है।
घीस

ध्यान दें कि classifyएक स्ट्रिंग लौटाता है, आपको constantizeइसे वास्तविक वर्ग में बदलने के लिए बाद में कॉल करना होगा।
स्टीफन

1
इसके साथ एक महत्वपूर्ण चेतावनी classifyयह है कि बहुवचन तार विलक्षण हो जाएंगे ... 'age_in_years'.classifyबन जाता हैAgeInYear
br3nt

@ br3nt यह एक्टिवरकॉर्ड के बाद से बहुवचन नहीं करता है4.2.11
Ulysse BN

23

स्रोत: 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"

6
@ पहिएदारियो यदि पहिया को ActiveSupport कहा जाता है , तो कृपया इसे पुनः स्थापित करें।
शिम

मुझे लगता है कि लोअरकेस वेरिएंट गलत है। इंजेक्शन ब्लॉक को सीधे बफर में हेरफेर नहीं करना चाहिए, लेकिन बफर के लिए नया मान self.split('_').inject([]){ |buffer,e| buffer + [buffer.empty? ? e : e.capitalize] }.join
लौटाएं

19

शुद्ध रूबी समाधान के लिए बेंचमार्क

मैंने हर संभावना को ध्यान में रखते हुए इसे शुद्ध रूबी कोड के साथ किया, यहाँ वे हैं:

  • पूंजीकरण और gsub

    'app_user'.capitalize.gsub(/_(\w)/){$1.upcase}
  • विभाजन और &शॉर्टहैंड का उपयोग करके नक्शा (उपयोगकर्ता 3869936 के जवाब के लिए धन्यवाद)

    '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)

11

मैं यहाँ आपके प्रश्न के विलोम की तलाश में, ऊँट के मामले से साँप के मामले में जा रहा था। उस के लिए अंडरस्कोर का उपयोग करें (डीमेलिज़ाइज़ नहीं):

AppUser.name.underscore # => "app_user"

या, यदि आपके पास पहले से ही एक ऊंट केस स्ट्रिंग है:

"AppUser".underscore # => "app_user"

या, यदि आप तालिका का नाम प्राप्त करना चाहते हैं, जो संभवत: इसीलिए आप सांप का मामला चाहते हैं:

AppUser.name.tableize # => "app_users"


क्यों नहीं उपयोग कर रहे हैं AppUser.table_name? यदि यह app_users नहीं है, लेकिन कहीं और परिभाषित किया गया है, तो आप सही तालिका का नाम भी सुनिश्चित करेंगे।
उलीसे बीएन

3

मुझे यहाँ और उत्तर जोड़ने में थोड़ी असहजता महसूस हो रही है। सबसे पठनीय और न्यूनतम शुद्ध रूबी दृष्टिकोण के लिए जाने का फैसला किया, @ 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"

1
ऊंट का मामला वास्तव में पहले कम है। अन्यथा इसे पास्कलकेस (या कभी-कभी ऊपरी ऊंट का मामला) का नाम दिया गया है। हालांकि इस प्रश्न में यह अस्पष्ट है!
उलेसे बीएन

2
@UlysseBN, tbh मैं शब्दों के इतिहास में नहीं हूँ। विकिपीडिया के दावे PascalCaseका एक सबसेट है CamelCase। यह भी मुझे पता है - कि ऊंट का मामला दोनों पर लागू होता है। लेकिन मैंने कभी जांच नहीं की। PascalCase का उल्लेख करने के लिए धन्यवाद। en.wikipedia.org/wiki/Camel_case
akostadinov

2
यह पृष्ठ imo पर सबसे अच्छा जवाब है। यह अच्छा होगा यदि :methodसंस्करण ने downcaseपहले किया तो इसका उपयोग दोनों पर किया जा सकता है lower_snake_caseऔर UPPER_SNAKE_CASE
स्केडल सेप

0

यहां सूचीबद्ध अन्य विधियों में से अधिकांश रेल विशिष्ट हैं। यदि आप शुद्ध रूबी के साथ ऐसा करना चाहते हैं, तो सबसे संक्षिप्त तरीका है जिसके साथ मैं आया हूं (सुझाए गए सुधार के लिए @ ulysse-bn को धन्यवाद)

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

"ऊंट केस" की आपकी परिभाषा बहुत सीमित है। जावा, और रूबी में कक्षा नाम, उदाहरण के लिए, कर रहे हैं ऊंट मामले MyFavoriteClass ... लेकिन वे भी एक कम मामलों प्रारंभिक पत्र की जरूरत नहीं है। कभी-कभी ऊंट के मामले में शुरुआती कैप होते हैं। कभी-कभी ऐसा नहीं होता।
मासुकोमी

2 रेगेक्स का उपयोग करना जहां आप केवल एक का उपयोग कर सकते हैं ओवरकिल है। आप केवल गैर कैप्चरिंग समूह का उपयोग कर सकते हैं:x.gsub(/(?:_|^)(\w)/){$1.upcase}
Ulysse BN

@UlysseBN, और हम आपके gsubसमाधान पर वापस आ गए हैं, ऐसा लगता है कि mapसमाधान की तुलना में धीमी है ।
अकोस्टैडिनोव

0

ऊँचा जोड़ने के लिए स्ट्रिंग बढ़ाएँ

शुद्ध रूबी में आप रेलगाड़ियों को रेल के समान कोड का उपयोग करके बढ़ा सकते हैं .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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.