सुरुचिपूर्ण पायथन समारोह CamelCase को साँप_केस में बदलने के लिए?


333

उदाहरण:

>>> convert('CamelCase')
'camel_case'

28
दूसरी दिशा में बदलने के लिए, यह अन्य स्टैकओवरफ़्लो प्रश्न देखें।
नाथन

10
nb वह NotCamelCaseलेकिनthisIs
मैट रिचर्ड्स

5
@MattRichards यह विवाद का विषय है। wiki
NO_NAME

@MattRichards उदाहरण के लिए जावा में वे दोनों का उपयोग करते हैं, CamelCase का उपयोग वर्ग परिभाषाओं के नामकरण के लिए किया जाता है, जबकि CamelCase का उपयोग प्रारंभिक चर नामकरण के लिए किया जाता है।
अंधेरा

जवाबों:


797

साँप के मामले में ऊंट का मामला

import re

name = 'CamelCaseName'
name = re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
print(name)  # camel_case_name

यदि आप ऐसा कई बार करते हैं और ऊपर धीमा है, तो रेगेक्स को पहले से संकलित करें:

pattern = re.compile(r'(?<!^)(?=[A-Z])')
name = pattern.sub('_', name).lower()

विशेष रूप से अधिक उन्नत मामलों को संभालने के लिए (यह अब प्रतिवर्ती नहीं है):

def camel_to_snake(name):
  name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
  return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()

print(camel_to_snake('camel2_camel2_case'))  # camel2_camel2_case
print(camel_to_snake('getHTTPResponseCode'))  # get_http_response_code
print(camel_to_snake('HTTPResponseCodeXYZ'))  # http_response_code_xyz

सांप का मामला ऊंट के मामले में

name = 'snake_case_name'
name = ''.join(word.title() for word in name.split('_'))
print(name)  # SnakeCaseName

1
यह समाधान इन मामलों में विफल रहता है: _test_Method, __test__Method, _Test, getHTTPresponseCode, __CamelCase, और _Camel_Case।
फ्रीग्नू

6
कैसे रिवर्स के बारे में? में कनवर्ट not_camel_caseकरें notCamelCaseऔर / या NotCamelCase?
जॉन

9
कैमल_केस को परिवर्तित करते समय दोहरे अंडरस्कोर से बचने के लिए, इस पंक्ति को जोड़ें:s2.replace('__', '_')
मार्कस

2
ध्यान दें यह बहुत प्रतिवर्ती नहीं है। getHTTPResponseCode को get_h_t_t_p_response_code में बदलना चाहिए। getHttpResponseCode को get_http_response_code
K2xL

4
@AnmolSinghJaggi पहला रेगेक्स एक संक्षिप्त शब्द के किनारे के मामले को दूसरे शब्द (जैसे "HTTPResponse" -> "HTTP_Response") या किसी आरंभिक लोअरकेस शब्द के अधिक सामान्य मामले के बाद एक पूंजीकृत शब्द (उदाहरण के लिए "getResponse" -> "को हैंडल करता है) get_Response "। दूसरा रेगेक्स दो गैर-समकेंद्रों (जैसे" ResponseCode "->" Response_Code ") के सामान्य मामले को नियंत्रित करता है, इसके बाद सब कुछ कम करने के लिए एक अंतिम कॉल करता है। > "get_http_response_code"
जेफ़ मोसर

188

पैकेज इंडेक्स में एक विभक्ति पुस्तकालय है जो आपके लिए इन चीजों को संभाल सकता है। इस मामले में, आप inflection.underscore()निम्न की तलाश करेंगे :

>>> inflection.underscore('CamelCase')
'camel_case'

44
मुझे समझ में नहीं आता है कि जब कोई महान पुस्तकालय इस कार्य को करता है तो लोग कस्टम फ़ंक्शंस का उपयोग क्यों कर रहे हैं। हमें पहिया को सुदृढ़ नहीं करना चाहिए।
Oden

88
@oden हो सकता है क्योंकि एक एकल-पंक्ति फ़ंक्शन का काम करने के लिए एक पूरी नई निर्भरता को जोड़ना नाजुक अधिकता है ?
सेसिल करी

11
एक उदाहरण के लिए, सुनिश्चित करें कि यह ओवरकिल है। एक बड़े आवेदन के पार, पहिया को सुदृढ़ और बाधित करने की कोई आवश्यकता नहीं है।
ब्रैड कोच

11
Regexes एक "सिंगल लाइन" में बहुत कुछ वापस करता है, यही कारण है कि यह उचित परीक्षण के साथ एक से अधिक लाइन है।
studgeek

12
@CecilCurry: मुझे यकीन है कि आप एक बेहतरीन प्रोग्रामर हैं, लेकिन मुझे यकीन नहीं है कि ऐसे मामले नहीं हैं, जिन पर आपने विचार नहीं किया है - उदाहरण के लिए यहां अन्य उत्तरों को देखें। इसलिए मैं हमेशा एक पुस्तकालय का चयन करूंगा, क्योंकि यह सिर्फ मेरे मुकाबले कई और देवों का अनुभव है।
माइकल शेपर

104

मुझे नहीं पता कि ये सब इतने जटिल क्यों हैं।

अधिकांश मामलों के लिए, सरल अभिव्यक्ति ([A-Z]+)ट्रिक करेगी

>>> re.sub('([A-Z]+)', r'_\1','CamelCase').lower()
'_camel_case'  
>>> re.sub('([A-Z]+)', r'_\1','camelCase').lower()
'camel_case'
>>> re.sub('([A-Z]+)', r'_\1','camel2Case2').lower()
'camel2_case2'
>>> re.sub('([A-Z]+)', r'_\1','camelCamelCase').lower()
'camel_camel_case'
>>> re.sub('([A-Z]+)', r'_\1','getHTTPResponseCode').lower()
'get_httpresponse_code'

पहले किरदार को नज़रअंदाज़ करने के लिए बस पीछे नज़र डालें (?!^)

>>> re.sub('(?!^)([A-Z]+)', r'_\1','CamelCase').lower()
'camel_case'
>>> re.sub('(?!^)([A-Z]+)', r'_\1','CamelCamelCase').lower()
'camel_camel_case'
>>> re.sub('(?!^)([A-Z]+)', r'_\1','Camel2Camel2Case').lower()
'camel2_camel2_case'
>>> re.sub('(?!^)([A-Z]+)', r'_\1','getHTTPResponseCode').lower()
'get_httpresponse_code'

यदि आप ALLCaps को all_caps से अलग करना चाहते हैं और अपनी स्ट्रिंग में संख्याओं की अपेक्षा करते हैं, तब भी आपको दो अलग-अलग रन करने की आवश्यकता नहीं है, बस |इस अभिव्यक्ति का उपयोग ((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))पुस्तक के हर परिदृश्य के बारे में कर सकते हैं

>>> a = re.compile('((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))')
>>> a.sub(r'_\1', 'getHTTPResponseCode').lower()
'get_http_response_code'
>>> a.sub(r'_\1', 'get2HTTPResponseCode').lower()
'get2_http_response_code'
>>> a.sub(r'_\1', 'get2HTTPResponse123Code').lower()
'get2_http_response123_code'
>>> a.sub(r'_\1', 'HTTPResponseCode').lower()
'http_response_code'
>>> a.sub(r'_\1', 'HTTPResponseCodeXYZ').lower()
'http_response_code_xyz'

यह सब इस बात पर निर्भर करता है कि आप क्या चाहते हैं ताकि समाधान का उपयोग करें जो आपकी आवश्यकताओं के लिए सबसे अच्छा है क्योंकि यह अत्यधिक जटिल नहीं होना चाहिए।

एन ज्वॉय!


1
अंतिम पुनरावृत्ति सबसे चतुर, IMO है। मुझे यह समझने में थोड़ी मुश्किल हुई कि यह केवल प्रत्येक शब्द की शुरुआत में एकल चरित्र की जगह ले रहा है - और यह केवल इसलिए था क्योंकि दृष्टिकोण एक से अलग था जो मैं खुद के साथ आया था। अच्छी तरह से किया।
जस्टिन मिलर

2
मैं (?!^)एक नज़र पीछे कहे जा रहे अभिव्यक्ति से हैरान था । जब तक मैं कुछ याद नहीं कर रहा हूं, तब तक हम वास्तव में यहां क्या चाहते हैं, एक नकारात्मक रूप है, जिसके पीछे व्यक्त किया जाना चाहिए (?<!^)। जिन कारणों से मैं आपके नकारात्मक रूप को समझ नहीं पा रहा हूं-आगे (?!^)भी काम करने लगता है, ...
एपर्टेक्स

7
यह अच्छी तरह से अंडरस्कोरिंग को नियंत्रित नहीं करता है: "Camel2WARNING_Case_CASE"बन जाता है "camel2_warning_case__case"। आप (?<!_)इसे हल करने के लिए, एक नकारात्मक लुकअप जोड़ सकते हैं : re.sub('((?<=[a-z0-9])[A-Z]|(?!^)(?<!_)[A-Z](?=[a-z]))', r'_\1', "Camel2WARNING_Case_CASE").lower() रिटर्न 'camel2_warning_case_case'
luckydonald

@Apteryx तुम सही हो, (?!^)को गलत तरीके से एक "पीछे देखो" कहा जाता था और इसके बजाय एक नकारात्मक रूपांतर कहा जाना चाहिए था । जैसा कि यह अच्छा स्पष्टीकरण दिखाता है, नकारात्मक लुकहैड्स आमतौर पर उस अभिव्यक्ति के बाद आते हैं जिसे आप खोज रहे हैं। तो आप के (?!^)रूप में सोच सकते हैं "खोजने के लिए ''जहां <start of string>का पालन नहीं करता है"। वास्तव में, एक नकारात्मक खोज भी काम करती है: आप (?<!^)" ''जहां <start of string>पूर्ववर्ती नहीं है" के रूप में सोच सकते हैं ।
नाथनियल जोन्स


11

व्यक्तिगत रूप से मुझे यकीन नहीं है कि अजगर में नियमित अभिव्यक्ति का उपयोग करने वाली किसी भी चीज को कैसे सुरुचिपूर्ण के रूप में वर्णित किया जा सकता है। यहां ज्यादातर जवाब सिर्फ "कोड गोल्फ" टाइप आरई ट्रिक्स हैं। एलिगेंट कोडिंग को आसानी से समझा जा सकता है।

def to_snake_case(not_snake_case):
    final = ''
    for i in xrange(len(not_snake_case)):
        item = not_snake_case[i]
        if i < len(not_snake_case) - 1:
            next_char_will_be_underscored = (
                not_snake_case[i+1] == "_" or
                not_snake_case[i+1] == " " or
                not_snake_case[i+1].isupper()
            )
        if (item == " " or item == "_") and next_char_will_be_underscored:
            continue
        elif (item == " " or item == "_"):
            final += "_"
        elif item.isupper():
            final += "_"+item.lower()
        else:
            final += item
    if final[0] == "_":
        final = final[1:]
    return final

>>> to_snake_case("RegularExpressionsAreFunky")
'regular_expressions_are_funky'

>>> to_snake_case("RegularExpressionsAre Funky")
'regular_expressions_are_funky'

>>> to_snake_case("RegularExpressionsAre_Funky")
'regular_expressions_are_funky'

1
+=तार पर लगभग हमेशा एक बुरा विचार है। एक सूची में संलग्न करें और ''.join()इसे अंत में। या इस मामले में, बस इसे एक अंडरस्कोर के साथ जोड़ दें ...
ThiefMaster

21
कैसे एक एकल लाइन नियमित अभिव्यक्ति नहीं स्वाभाविक तौर पर में बेहतर बस हर व्यावहारिक तरीका (पठनीयता सहित) अक्षम बहु लाइन चरित्र यात्रा और जानवर बल स्ट्रिंग munging करने के बारे में? पायथन एक कारण के लिए नियमित अभिव्यक्ति सहायता प्रदान करता है।
सेसिल करी

1
@CecilCurry - नियमित अभिव्यक्ति बहुत जटिल हैं। संकलक और पार्सर देखें जो पायथन उपयोग करता है: svn.python.org/projects/python/trunk/Lib/sre_compile.py & svn.python.org/projects/python/nunk/Lib/sre_parse.py - सरल स्ट्रिंग हेरफेर जैसे यह आरई एक ही कर की तुलना में बहुत तेजी से होने की संभावना है।
इवान बोर्गस्ट्रॉम

1
+1। Regexes एक वास्तविक CPU सिंक हो सकता है, और गहन गणनाओं पर नाटकीय रूप से आपके प्रदर्शन को कम करेगा। सरल कार्यों के लिए, हमेशा सरल कार्यों को प्राथमिकता दें।
फेबियन

4
"सरल कार्यों के लिए, हमेशा सरल कार्यों को प्राथमिकता दें" निश्चित रूप से अच्छी सलाह है, लेकिन यह जवाब न तो एक सरल कार्य है और न ही एक सुरुचिपूर्ण। रेगेक्स धीमा हो सकता है, लेकिन इस तरह के एक जटिल फ़ंक्शन को डिफ़ॉल्ट करना (जो कि ALSO भी है और इसमें त्रुटि के कई संभावित बिंदु हैं) पूरी तरह से समय से पहले अनुकूलन है
kevlarr

9

reयदि संभव हो तो मैं बचना पसंद करता हूं :

def to_camelcase(s):
    return ''.join(['_' + c.lower() if c.isupper() else c for c in s]).lstrip('_')
>>> to_camelcase("ThisStringIsCamelCase")
'this_string_is_camel_case'

1
यह सबसे कॉम्पैक्ट एक है जो reलाइब्रेरी का उपयोग करने से बचता है और केवल एक लाइन में सामान का निर्माण करता है जो केवल बिल्ट-इन str.methods का उपयोग करता है! यह इस उत्तर के समान है , लेकिन if ... elseपहले अक्षर के रूप में संभावित रूप से जोड़े गए "_" को अलग करके स्लाइसिंग और अतिरिक्त का उपयोग करने से बचा जाता है । मुझे यह सबसे ज्यादा पसंद है।
बृहस्पतिवार

स्वीकृत उत्तर के लिए 6.81 µs ± 22.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)लेकिन इस प्रतिक्रिया के लिए 2.51 µs ± 25.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)जो 2.5 गुना अधिक तेज़ है! इसे प्रेम करें!
WBAR


7

मुझे लगता है कि यह समाधान पिछले उत्तरों की तुलना में अधिक सीधा है:

import re

def convert (camel_input):
    words = re.findall(r'[A-Z]?[a-z]+|[A-Z]{2,}(?=[A-Z][a-z]|\d|\W|$)|\d+', camel_input)
    return '_'.join(map(str.lower, words))


# Let's test it
test_strings = [
    'CamelCase',
    'camelCamelCase',
    'Camel2Camel2Case',
    'getHTTPResponseCode',
    'get200HTTPResponseCode',
    'getHTTP200ResponseCode',
    'HTTPResponseCode',
    'ResponseHTTP',
    'ResponseHTTP2',
    'Fun?!awesome',
    'Fun?!Awesome',
    '10CoolDudes',
    '20coolDudes'
]
for test_string in test_strings:
    print(convert(test_string))

कौन से आउटपुट:

camel_case
camel_camel_case
camel_2_camel_2_case
get_http_response_code
get_200_http_response_code
get_http_200_response_code
http_response_code
response_http
response_http_2
fun_awesome
fun_awesome
10_cool_dudes
20_cool_dudes

नियमित अभिव्यक्ति तीन पैटर्न से मेल खाती है:

  1. [A-Z]?[a-z]+: लगातार निचले-मामले वाले पत्र जो वैकल्पिक रूप से ऊपरी-केस पत्र के साथ शुरू होते हैं।
  2. [A-Z]{2,}(?=[A-Z][a-z]|\d|\W|$): दो या अधिक लगातार ऊपरी मामले के पत्र। यदि यह निम्न-केस पत्र द्वारा पीछा किया जाता है, तो पिछले ऊपरी मामले के पत्र को बाहर करने के लिए एक लुकहेड का उपयोग करता है।
  3. \d+: लगातार संख्या।

का उपयोग करके re.findallहम अलग-अलग "शब्दों" की एक सूची प्राप्त करते हैं जिसे निचले-मामले में परिवर्तित किया जा सकता है और अंडरस्कोर के साथ जोड़ा जा सकता है।


1
न्यूमेरिकल्स को स्वतंत्र रूप से प्राप्त करने के लिए यहाँ एक अच्छा उदाहरण है।
math_law

1
टूटा हुआ: कन्वर्ट ("ए बी") -> 'ए'
ऐडव

5

मुझे पता नहीं है कि दोनों .sub () कॉल का उपयोग क्यों किया जा रहा है? :) मैं रेगेक्स गुरु नहीं हूं, लेकिन मैंने इसे सरल बनाया है, जो मेरी कुछ जरूरतों के लिए उपयुक्त है, मुझे बस एक समाधान की आवश्यकता है, जो कि कैमलडैडवेर्स को POST के अनुरोध से vars_with_underscore में परिवर्तित कर सकता है:

def myFunc(...):
  return re.sub('(.)([A-Z]{1})', r'\1_\2', "iTriedToWriteNicely").lower()

यह getHTTPResponse जैसे नामों के साथ काम नहीं करता है, क्योंकि मैंने सुना है कि यह बुरा नामकरण सम्मेलन है (getHttpResponse की तरह होना चाहिए, यह स्पष्ट है, कि यह इस फॉर्म को याद रखना बहुत आसान है)।


मैं उल्लेख करना भूल गया, कि '{1}' की जरूरत नहीं है, लेकिन कभी-कभी यह कुछ धुंध को स्पष्ट करने में मदद करता है।
desper4do

2
-1: यह सिर्फ काम नहीं करता है। उदाहरण के साथ प्रयास करें 'HTTPConnectionFactory', आपके कोड का उत्पादन होता है 'h_tt_pconnection_factory', स्वीकृत उत्तर से कोड का उत्पादन होता है'http_connection_factory'
vartec

4

यहाँ मेरा समाधान है:

def un_camel(text):
    """ Converts a CamelCase name into an under_score name. 

        >>> un_camel('CamelCase')
        'camel_case'
        >>> un_camel('getHTTPResponseCode')
        'get_http_response_code'
    """
    result = []
    pos = 0
    while pos < len(text):
        if text[pos].isupper():
            if pos-1 > 0 and text[pos-1].islower() or pos-1 > 0 and \
            pos+1 < len(text) and text[pos+1].islower():
                result.append("_%s" % text[pos].lower())
            else:
                result.append(text[pos].lower())
        else:
            result.append(text[pos])
        pos += 1
    return "".join(result)

यह टिप्पणियों में चर्चा किए गए उन कोने के मामलों का समर्थन करता है। उदाहरण के लिए, यह बदल देंगे getHTTPResponseCodeकरने के लिए get_http_response_codeकी तरह होना चाहिए।


7
-1 क्योंकि यह regexps का उपयोग करने की तुलना में बहुत जटिल है।
एरिक ओ लेबिगॉट

7
ईओएल, मुझे यकीन है कि बहुत से गैर-रेगेक्स लोग अन्यथा सोचेंगे।
इवान फॉसमार्क

यह समाधान इन मामलों में विफल रहता है: _Method, _test_Method , __test__Method, getHTTPrespnseCode, __get_HTTPresponseCode, _Camel_Case, _Test, और _test_Method।
फ्रीग्नू

3
@ इवान, वे लोग बुरे प्रोग्रामर होंगे।
जेसी ढिल्लों

3

इसके मज़े के लिए:

>>> def un_camel(input):
...     output = [input[0].lower()]
...     for c in input[1:]:
...             if c in ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
...                     output.append('_')
...                     output.append(c.lower())
...             else:
...                     output.append(c)
...     return str.join('', output)
...
>>> un_camel("camel_case")
'camel_case'
>>> un_camel("CamelCase")
'camel_case'

या, इसके मज़े के लिए और अधिक:

>>> un_camel = lambda i: i[0].lower() + str.join('', ("_" + c.lower() if c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" else c for c in i[1:]))
>>> un_camel("camel_case")
'camel_case'
>>> un_camel("CamelCase")
'camel_case'

3
c.isupper () के बजाय ABCEF में c ... Z
जिमी

1
पायथन में रेगेक्स नहीं है? एक त्वरित 's / [az] \ K ([AZ] [az]) / _ \ L $ 1 / g; Perl में lc $ _ 'काम करता है (हालाँकि यह getHTTPResponseCode को अच्छी तरह से हैंडल नहीं करता है, लेकिन यह अपेक्षित है, कि इसका नाम getHttpResponseCode रखा जाए)
jrockway

5
str.joinउम्र के लिए पदावनत कर दिया गया है''.join(..)इसके बजाय उपयोग करें ।
जॉन फोहि जूल

jrockway: इसमें "re" मॉड्यूल के माध्यम से नियमित अभिव्यक्ति होती है। यहां पोस्ट किए गए दृष्टिकोणों के बजाय रेगेक्स का उपयोग करके इस काम को करना बहुत मुश्किल नहीं होना चाहिए।
मैथ्यू इसेलिन

अजगर यहाँ noob, लेकिन क्यों str.join ('', आउटपुट) वापस? बस एक प्रति बनाने के लिए?
टार्क

3

रेगेक्स का उपयोग करना सबसे कम हो सकता है, लेकिन यह समाधान अधिक पठनीय है:

def to_snake_case(s):
    snake = "".join(["_"+c.lower() if c.isupper() else c for c in s])
    return snake[1:] if snake.startswith("_") else snake

@blueyed जो पूरी तरह से असंबंधित है, इस सवाल का django से कोई लेना-देना नहीं है।
3k-

यह केवल एक उदाहरण है, जैसे HTTPResponseCode, जिसे stackoverflow.com/a/23561109/15690 द्वारा नियंत्रित किया जाता है ।
blueyed

3

इतने सारे जटिल तरीके ... बस सभी "शीर्षक" समूह को ढूंढें और इसके निचले आवरण वाले संस्करण को अंडरस्कोर के साथ जोड़ दें।

>>> import re
>>> def camel_to_snake(string):
...     groups = re.findall('([A-z0-9][a-z]*)', string)
...     return '_'.join([i.lower() for i in groups])
...
>>> camel_to_snake('ABCPingPongByTheWay2KWhereIsOurBorderlands3???')
'a_b_c_ping_pong_by_the_way_2_k_where_is_our_borderlands_3'

यदि आप समूह के पहले वर्ण या अलग समूह जैसे नंबर नहीं बनाना चाहते हैं - तो आप ([A-z][a-z0-9]*)मास्क का उपयोग कर सकते हैं ।



2

यह एक सुरुचिपूर्ण विधि नहीं है, एक सरल राज्य मशीन (बिटफील्ड स्टेट मशीन) का एक बहुत 'निम्न स्तर' का कार्यान्वयन है, संभवतः इसे हल करने के लिए सबसे अधिक एंटी पाइथोनिक मोड है, हालांकि इस सरल को हल करने के लिए पुन: मॉड्यूल भी एक जटिल राज्य मशीन को लागू करता है कार्य, इसलिए मुझे लगता है कि यह एक अच्छा समाधान है।

def splitSymbol(s):
    si, ci, state = 0, 0, 0 # start_index, current_index 
    '''
        state bits:
        0: no yields
        1: lower yields
        2: lower yields - 1
        4: upper yields
        8: digit yields
        16: other yields
        32 : upper sequence mark
    '''
    for c in s:

        if c.islower():
            if state & 1:
                yield s[si:ci]
                si = ci
            elif state & 2:
                yield s[si:ci - 1]
                si = ci - 1
            state = 4 | 8 | 16
            ci += 1

        elif c.isupper():
            if state & 4:
                yield s[si:ci]
                si = ci
            if state & 32:
                state = 2 | 8 | 16 | 32
            else:
                state = 8 | 16 | 32

            ci += 1

        elif c.isdigit():
            if state & 8:
                yield s[si:ci]
                si = ci
            state = 1 | 4 | 16
            ci += 1

        else:
            if state & 16:
                yield s[si:ci]
            state = 0
            ci += 1  # eat ci
            si = ci   
        print(' : ', c, bin(state))
    if state:
        yield s[si:ci] 


def camelcaseToUnderscore(s):
    return '_'.join(splitSymbol(s)) 

splitsymbol सभी प्रकार के मामलों को पार्स कर सकता है:

मुझे उम्मीद है कि यह उपयोगी है


1
घृणित, लेकिन यह मेरी मशीन पर रेगेक्स विधि की तुलना में लगभग 3x तेज है। :)
jdiaz5513


1

उत्कृष्ट स्कैमैटिक्स लिब पर एक नज़र डालें

https://github.com/schematics/schematics

यह आपको टाइप किए गए डेटा संरचनाएं बनाने की अनुमति देता है जो कि अजगर से जावास्क्रिप्ट स्वाद के लिए सीरियल / डिसेरलाइज़ कर सकते हैं, जैसे:

class MapPrice(Model):
    price_before_vat = DecimalType(serialized_name='priceBeforeVat')
    vat_rate = DecimalType(serialized_name='vatRate')
    vat = DecimalType()
    total_price = DecimalType(serialized_name='totalPrice')

1

यह सरल विधि काम करना चाहिए:

import re

def convert(name):
    return re.sub(r'([A-Z]*)([A-Z][a-z]+)', lambda x: (x.group(1) + '_' if x.group(1) else '') + x.group(2) + '_', name).rstrip('_').lower()
  • हम ऐसे बड़े अक्षरों की तलाश करते हैं जो किसी भी संख्या (या शून्य) के बड़े अक्षरों से पहले हो, और उसके बाद किसी भी संख्या में छोटे अक्षर हों।
  • एक अंडरस्कोर को समूह में पाए जाने वाले अंतिम कैपिटल लेटर की घटना से ठीक पहले रखा जाता है, और किसी को उस कैपिटल लेटर से पहले रखा जा सकता है, जब यह अन्य कैपिटल लेटर्स से पहले होता है।
  • यदि अंडरस्कोरिंग के निशान हैं, तो उन्हें हटा दें।
  • अंत में, पूरे परिणाम स्ट्रिंग को निचले मामले में बदल दिया जाता है।

( यहां से लिया गया काम ऑनलाइन देखें )


यह विपरीत प्रश्न ( ऊंट मामले में कैसे परिवर्तित किया जाए ) के लिए एक उत्तर है ।
जस्टिन

1

वाह मैं अभी यह django स्निपेट्स से चुरा लिया। रेफरी http://djangosnippets.org/snippets/585/

बहुत सुंदर

camelcase_to_underscore = lambda str: re.sub(r'(?<=[a-z])[A-Z]|[A-Z](?=[^A-Z])', r'_\g<0>', str).lower().strip('_')

उदाहरण:

camelcase_to_underscore('ThisUser')

यह दिखाता है:

'this_user'

REGEX डेमो


1
एक स्थानीय चर नाम के रूप में str का उपयोग करके खराब रूप।
freegnu

यह बुरी तरह से विफल रहता है अगर किसी स्ट्रिंग की शुरुआत या अंत में कोई अंडरस्कोर हैं और अगर किसी कैपिटल लेटर से पहले कोई अंडरस्कोर हैं।
फ्रीग्नू

खाता संख्या does
villy393

0

नियमित अभिव्यक्तियों का उपयोग करके एक भयावह उदाहरण (आप इसे आसानी से साफ कर सकते हैं :)):

def f(s):
    return s.group(1).lower() + "_" + s.group(2).lower()

p = re.compile("([A-Z]+[a-z]+)([A-Z]?)")
print p.sub(f, "CamelCase")
print p.sub(f, "getHTTPResponseCode")

हालांकि getHTTPResponseCode के लिए काम करता है!

वैकल्पिक रूप से, लैम्बडा का उपयोग कर:

p = re.compile("([A-Z]+[a-z]+)([A-Z]?)")
print p.sub(lambda x: x.group(1).lower() + "_" + x.group(2).lower(), "CamelCase")
print p.sub(lambda x: x.group(1).lower() + "_" + x.group(2).lower(), "getHTTPResponseCode")

संपादित करें: यह भी देखना बहुत आसान होना चाहिए कि "टेस्ट" जैसे मामलों में सुधार के लिए जगह है, क्योंकि अंडरस्कोर को अनजाने में डाला जाता है।


0

यहाँ कुछ मैंने हेडर को टैब-सीमांकित फ़ाइल में बदलने के लिए किया है। मैं उस हिस्से को छोड़ रहा हूं जहां मैंने केवल फ़ाइल की पहली पंक्ति को संपादित किया है। आप इसे आसानी से फिर से पुस्तकालय के साथ पायथन के लिए अनुकूलित कर सकते हैं। इसमें संख्याओं को अलग करना भी शामिल है (लेकिन अंकों को साथ रखता है)। मैंने इसे दो चरणों में किया क्योंकि यह बताने से ज्यादा आसान था कि लाइन या टैब की शुरुआत में अंडरस्कोर न लगाएं।

एक कदम ... अपरकेस अक्षर या निचले अक्षरों से पहले पूर्णांक खोजें, और उन्हें एक अंडरस्कोर के साथ पूर्ववर्ती करें:

खोज:

([a-z]+)([A-Z]|[0-9]+)

रिप्लेसमेंट:

\1_\l\2/

दो कदम ... ऊपर ले लो और फिर से चलाने के लिए सभी टोपियां लोअरकेस में परिवर्तित करें:

खोज:

([A-Z])

प्रतिस्थापन (यह बैकस्लैश, लोअरकेस एल, बैकस्लैश, एक):

\l\1

0

मैं उसी समस्या के समाधान की तलाश में था, सिवाय इसके कि मुझे एक श्रृंखला की आवश्यकता थी; जैसे

"CamelCamelCamelCase" -> "Camel-camel-camel-case"

यहाँ दो-स्तरीय अच्छे समाधानों से शुरुआत करते हुए, मैं निम्नलिखित बातों के साथ आया:

"-".join(x.group(1).lower() if x.group(2) is None else x.group(1) \
         for x in re.finditer("((^.[^A-Z]+)|([A-Z][^A-Z]+))", "stringToSplit"))

अधिकांश जटिल तर्क पहले शब्द को कम करने से बचने के लिए है। यदि आप पहले शब्द को बदलने में कोई आपत्ति नहीं करते हैं तो यहां एक सरल संस्करण दिया गया है:

"-".join(x.group(1).lower() for x in re.finditer("(^[^A-Z]+|[A-Z][^A-Z]+)", "stringToSplit"))

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


0

नियमित अभिव्यक्तियों के बिना संक्षिप्त करें, लेकिन HTTPResponseCode => canpresponse_code:

def from_camel(name):
    """
    ThisIsCamelCase ==> this_is_camel_case
    """
    name = name.replace("_", "")
    _cas = lambda _x : [_i.isupper() for _i in _x]
    seq = zip(_cas(name[1:-1]), _cas(name[2:]))
    ss = [_x + 1 for _x, (_i, _j) in enumerate(seq) if (_i, _j) == (False, True)]
    return "".join([ch + "_" if _x in ss else ch for _x, ch in numerate(name.lower())])

0

किसी भी पुस्तकालय के बिना:

def camelify(out):
    return (''.join(["_"+x.lower() if i<len(out)-1 and x.isupper() and out[i+1].islower()
         else x.lower()+"_" if i<len(out)-1 and x.islower() and out[i+1].isupper()
         else x.lower() for i,x in enumerate(list(out))])).lstrip('_').replace('__','_')

थोड़ा भारी, लेकिन

CamelCamelCamelCase ->  camel_camel_camel_case
HTTPRequest         ->  http_request
GetHTTPRequest      ->  get_http_request
getHTTPRequest      ->  get_http_request

0

इस साइट पर प्रस्तावित बहुत अच्छा RegEx :

(?<!^)(?=[A-Z])

अगर अजगर के पास स्ट्रींग स्प्लिट विधि है, तो उसे काम करना चाहिए ...

जावा में:

String s = "loremIpsum";
words = s.split("(?&#60;!^)(?=[A-Z])");

दुर्भाग्य से, पायथन नियमित अभिव्यक्ति मॉड्यूल (संस्करण 3.6 के रूप में) शून्य-लंबाई मैचों पर विभाजन का समर्थन नहीं करता है।
rspeed

0
def convert(name):
    return reduce(
        lambda x, y: x + ('_' if y.isupper() else '') + y, 
        name
    ).lower()

और अगर हमें पहले से अन-कैमेल्ड इनपुट वाले किसी मामले को कवर करने की आवश्यकता है:

def convert(name):
    return reduce(
        lambda x, y: x + ('_' if y.isupper() and not x.endswith('_') else '') + y, 
        name
    ).lower()

0

बस किसी को पूर्ण स्रोत फ़ाइल को बदलने की आवश्यकता होती है, यहां एक स्क्रिप्ट है जो इसे करेगी।

# Copy and paste your camel case code in the string below
camelCaseCode ="""
    cv2.Matx33d ComputeZoomMatrix(const cv2.Point2d & zoomCenter, double zoomRatio)
    {
      auto mat = cv2.Matx33d::eye();
      mat(0, 0) = zoomRatio;
      mat(1, 1) = zoomRatio;
      mat(0, 2) = zoomCenter.x * (1. - zoomRatio);
      mat(1, 2) = zoomCenter.y * (1. - zoomRatio);
      return mat;
    }
"""

import re
def snake_case(name):
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

def lines(str):
    return str.split("\n")

def unlines(lst):
    return "\n".join(lst)

def words(str):
    return str.split(" ")

def unwords(lst):
    return " ".join(lst)

def map_partial(function):
    return lambda values : [  function(v) for v in values]

import functools
def compose(*functions):
    return functools.reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x)

snake_case_code = compose(
    unlines ,
    map_partial(unwords),
    map_partial(map_partial(snake_case)),
    map_partial(words),
    lines
)
print(snake_case_code(camelCaseCode))

-1

मैं इस एक के साथ बहुत अच्छी किस्मत है:

import re
def camelcase_to_underscore(s):
    return re.sub(r'(^|[a-z])([A-Z])',
                  lambda m: '_'.join([i.lower() for i in m.groups() if i]),
                  s)

यह स्पष्ट रूप से गति के लिए अनुकूलित किया जा सकता है एक छोटे बिट यदि आप चाहते हैं।

import re

CC2US_RE = re.compile(r'(^|[a-z])([A-Z])')

def _replace(match):
    return '_'.join([i.lower() for i in match.groups() if i])

def camelcase_to_underscores(s):
    return CC2US_RE.sub(_replace, s)

-1
def convert(camel_str):
    temp_list = []
    for letter in camel_str:
        if letter.islower():
            temp_list.append(letter)
        else:
            temp_list.append('_')
            temp_list.append(letter)
    result = "".join(temp_list)
    return result.lower()

-3

उपयोग करें: str.capitalize()स्ट्रिंग के पहले अक्षर को (परिवर्तनीय str में समाहित) एक कैपिटल लेटर में बदलने के लिए और पूरे स्ट्रिंग को वापस लौटाता है।

उदाहरण: कमांड: "हैलो" .capitalize () आउटपुट: हैलो


यह सवाल से संबंधित नहीं है - OP CamelCase चाहता है -> स्नेककेस, कैपिटलाइज़ेशन नहीं।
ब्रैड कोच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.