CamelCaseをsnake_caseに変換するエレガントなPython関数?


333

例:

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

28
他の方向に変換するには、この他のスタックオーバーフローの質問を参照してください。
ネイサン、

10
nb that's NotCamelCasebutthisIs
マットリチャーズ

5
@MattRichardsそれは論争の問題です。wiki
NO_NAME、2015

@MattRichardsたとえば、Javaでは両方を使用します。キャメルケースはクラス定義の命名に使用され、キャメルケースは初期化された変数の命名に使用されます。
ダークレス

回答:


796

キャメルケースからスネークケース

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の場合に失敗します。
freegnu

6
逆はどうですか?not_camel_casenotCamelCaseやに変換しNotCamelCaseますか?
john2x 2011

9
:例えばcamel_Caseを変換する際に、二重のアンダースコアを避けるために、この行を追加s2.replace('__', '_')
マーカスAhlberg

2
これはあまり元に戻せないことに注意してください。getHTTPResponseCodeはget_h_t_t_p_response_codeに変換する必要があります。getHttpResponseCodeはget_http_response_codeに変換する必要があります
K2xL

4
@AnmolSinghJaggi最初の正規表現は、頭字語とそれに続く別の単語(例: "HTTPResponse"-> "HTTP_Response")のエッジケースを処理するか、大文字の単語が後に続く最初の小文字の単語(例: "getResponse"-> ")の通常のケースを処理します。 get_Response "。2番目の正規表現は、2つの非頭字語(例:" ResponseCode "->" Response_Code ")の後に、すべて小文字の最終呼び出しが続く通常のケースを処理します。したがって、" getHTTPResponseCode "->" getHTTP_ResponseCode "->" get_HTTP_Response_Code "- > "get_http_response_code"
Jeff Moser

188

パッケージインデックスには、これらのことを処理できる活用ライブラリがあります。この場合、あなたは探しているでしょうinflection.underscore()

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

44
このタスクを実行する優れたライブラリがあるのに、なぜカスタム関数の使用に賛成票を投じているのか理解できません。車輪を再発明すべきではありません。
おでん2015

87
@odenたぶん、単一の関数の仕事をするためにまったく新しい依存関係を追加することは、脆弱なやりすぎでしょうか?
Cecil Curry

11
1つの例として、それはやり過ぎです。より大きなアプリケーション全体で、ホイールを再発明して難読化する必要はありません。
Brad Koch

11
正規表現は多くの場合「単一行」に戻ります。そのため、適切なテストを行うと複数行になります。
studgeek

12
@CecilCurry:あなたが優れたプログラマであると確信していますが、検討していないケースがないかどうかはわかりません。例については、他の回答をご覧ください。それは私が常にライブラリを選択する理由です。なぜなら、それは私よりもはるかに多くの開発者の合計経験だからです。
Michael Scheper

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に分離し、文字列の数値を期待する場合は、2つの個別の実行を実行する必要はありません。|この式((?<=[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'

それはすべてあなたが望むものに依存するので、それは過度に複雑であってはならないので、あなたのニーズに最も適したソリューションを使用してください。

nJoy!


1
最後の反復は、最も賢いIMOです。各単語の先頭の1文字だけが置き換えられていることを理解するのに少し時間がかかりました。これは、私が思いついた方法とはアプローチが異なっていたためです。よくできました。
Justin Miller

2
後読み(?!^)と呼ばれる表現に戸惑いました。私が何かを逃していない限り、ここで本当に欲しいのは、として表現されるべき否定的な後読み(?<!^)です。理由のため、否定的な先読みも機能する(?!^)ように思えます...
Apteryx

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'
ラッキードナルド2017年

@Apteryxそうです、(?!^)誤って「後読み」と呼ばれ、代わりに否定先読み表明と呼ばれるべきでした。この素敵な説明を示し、負の先読みは通常、来た後の発現のためのあなたです検索。したがって(?!^)、「従わない''場所を見つける」と考えることができます<start of string>。実際、否定的な後読みも機能します。「先行しない場所を(?<!^)見つける」と考えることができます。''<start of string>
ナサニエルジョーンズ

17

stringcaseはこのためのライブラリです。例えば:

>>> from stringcase import pascalcase, snakecase
>>> snakecase('FooBarBaz')
'foo_bar_baz'
>>> pascalcase('foo_bar_baz')
'FooBarBaz'

11

個人的には、Pythonで正規表現を使用しているものをエレガントに表現できるかどうかはわかりません。ここでのほとんどの答えは、「コードゴルフ」タイプのREトリックを実行することです。エレガントなコーディングは簡単に理解できるはずです。

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
単一行の正規表現、非効率的な複数行文字の反復やブルートフォース文字列の変更よりも、実質的にすべての実用的な方法(読みやすさを含む)で本質的に優れているわけではありません。Pythonは、特別な理由から、標準で正規表現のサポートを提供しています。
Cecil Curry

1
@CecilCurry-正規表現は非常に複雑です。Pythonの使用するコンパイラおよびパーサを参照してください:svn.python.org/projects/python/trunk/Lib/sre_compile.pysvn.python.org/projects/python/trunk/Lib/sre_parse.pyを -のような単純な文字列操作これは、同じことを行うREよりもはるかに高速です。
Evan Borgstrom、2017

1
+1。正規表現は実際のCPUシンクになる可能性があり、集中的な計算ではパフォーマンスが劇的に低下します。単純なタスクの場合は、常に単純な関数を優先してください。
Fabien 2017

4
「単純なタスクでは常に単純な関数を好む」というのは間違いなく良いアドバイスですが、この答えは単純な関数でもエレガントでもありません。
正規表現

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のみを使用して1行でのみ処理を行う最もコンパクトなものです。これはこの回答に似ていますが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

8
''.join('_'+c.lower() if c.isupper() else c for c in "DeathToCamelCase").strip('_')
re.sub("(.)([A-Z])", r'\1_\2', 'DeathToCamelCase').lower()

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

正規表現は3つのパターンに一致します。

  1. [A-Z]?[a-z]+:オプションで大文字で始まる連続した小文字。
  2. [A-Z]{2,}(?=[A-Z][a-z]|\d|\W|$):2つ以上の連続した大文字。最後の大文字の後に小文字が続く場合は、先読みを使用して最後の大文字を除外します。
  3. \d+:連続番号。

を使用re.findallすると、小文字に変換してアンダースコアで結合できる個々の「単語」のリストを取得できます。


1
Numericsを独立してトークン化する良い例があります。
math_law

1
壊れた:convert( "aB")-> 'a'
adw

5

なぜ両方の.sub()呼び出しを使用するのかわかりませんか?:)私は正規表現の第一人者ではありませんが、関数をこの関数に簡略化しました。これは特定のニーズに適しています。camelCasedVarsを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 '23

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
これは、正規表現を使用する場合に比べて非常に複雑であるためです。
エリックOレビゴット2009

7
EOL、私は正規表現でない人々の多くがそうでなければ考えていると確信しています。
エヴァンフォスマルク2009

このソリューションは、_Method、_test_Method、__ test__Method、getHTTPrespnseCode、__ get_HTTPresponseCode、_Camel_Case、_Test、および_test_Methodの場合に失敗します。
freegnu

3
@Evan、それらの人々は悪いプログラマーでしょう。
ジェシーディロン

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
ABCEFのcではなくc.isupper()... Z
ジミー

1
Pythonには正規表現がありませんか?簡単な 's / [az] \ K([AZ] [az])/ _ \ L $ 1 / g; Perlのlc $ _ 'がその役割を果たします(ただし、getHTTPResponseCodeは適切に処理されませんが、それは当然です。getHttpResponseCodeという名前にする必要があります)
jrockway

5
str.join古くから非推奨になっています。''.join(..)代わりに使用してください。
John Fouhy、

jrockway:「re」モジュールを介した正規表現があります。ここに掲載されているアプローチではなく、正規表現を使用してこの作業を行うことはそれほど難しくありません。
マシューアイセリン

ここではPython noobですが、なぜstr.join( ''、output)を返すのですか?コピーを作成するだけですか?
タークス2009

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- 2015

それはHTTPResponseCodeによって処理されているように、単なる例ですstackoverflow.com/a/23561109/15690
2015

3

非常に多くの複雑な方法...すべての「Titled」グループを見つけて、アンダースコアで小文字のバリアントを結合します。

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

これはエレガントな方法ではなく、シンプルなステートマシン(ビットフィールドステートマシン)の非常に「低レベル」の実装であり、おそらくこれを解決するのに最も反Pythonicモードですが、reモジュールもこのシンプルな解決に複雑すぎるステートマシンを実装していますタスクなので、これは良い解決策だと思います。

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はすべてのケースタイプを解析できます:UpperSEQUENCEInterleaved、under_score、BIG_SYMBOLSおよびcammelCasedMethods

お役に立てれば幸いです


1
恐ろしいですが、私のマシンの正規表現メソッドより約3倍速く実行されます。:)
jdiaz5513 2014年


1

優れたSchematics libをご覧ください

https://github.com/schematics/schematics

PythonからJavascriptフレーバーにシリアル化/逆シリアル化できる型付きデータ構造を作成できます。例:

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スニペットから盗んだだけです。ref 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'

正規表現デモ


1
ローカル変数名としてstrを使用した不正な形式。
freegnu

文字列の先頭または末尾にアンダースコアがあり、大文字の前にアンダースコアがある場合、これは無意味に失敗します。
freegnu

😬口座番号にdoesntのテイク
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

これは、タブ区切りファイルのヘッダーを変更するために行ったものです。ファイルの最初の行だけを編集した部分は省略しています。reライブラリを使用すると、Pythonにかなり簡単に適合させることができます。これには、数字の分離も含まれます(ただし、数字は一緒に保持されます)。行またはタブの先頭にアンダースコアを付けないように指示するよりも簡単だったので、2つのステップでそれを行いました。

手順1 ...大文字または小文字の後に続く整数を検索し、それらの前にアンダースコアを付けます。

探す:

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

置換:

\1_\l\2/

ステップ2 ...上記を取り、再度実行してすべての大文字を小文字に変換します。

探す:

([A-Z])

置換(バックスラッシュ、小文字のL、バックスラッシュ、1つ):

\l\1

0

同じ問題の解決策を探していましたが、チェーンが必要でした。例えば

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

ここで2ワードの優れたソリューションから始めて、次のことを思いつきました。

"-".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 => httpresponse_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])

Pythonに文字列分割メソッドがある場合、それは動作するはずです...

Javaの場合:

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

残念ながら、Python正規表現モジュールは(バージョン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に含まれる)の最初の文字を大文字に変換し、文字列全体を返します。

例:コマンド: "hello" .capitalize()出力:Hello


これは質問とは関係ありません-OPはキャメル化ではなくCamelCase-> snake_caseを必要としています。
Brad Koch
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.