332

例:

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

30 に答える 30

1002

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

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

アンダースコアが 2 つ以上のケースも追加するには:

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

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

name = 'snake_case_name'
name = ''.join(word.title() for word in name.split('_'))
print(name)  # SnakeCaseName
于 2009-07-24T06:25:13.860 に答える
137

なぜこれらすべてがそれほど複雑なのかわかりません。

ほとんどの場合、単純な式([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!

于 2012-10-12T21:17:16.130 に答える
7
''.join('_'+c.lower() if c.isupper() else c for c in "DeathToCamelCase").strip('_')
re.sub("(.)([A-Z])", r'\1_\2', 'DeathToCamelCase').lower()
于 2009-07-24T01:48:27.700 に答える
5

両方の .sub() 呼び出しを使用する理由がわかりませんか? :) 私は正規表現の第一人者ではありませんが、特定のニーズに適した関数をこれに単純化しました。camelCasedVars を POST リクエストから vars_with_underscore に変換するソリューションが必要でした:

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

getHTTPResponse のような名前では機能しません。命名規則が悪いと聞いたからです (getHttpResponse のようにする必要があります。明らかに、この形式を覚える方がはるかに簡単です)。

于 2012-11-13T15:39:08.303 に答える
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

于 2009-07-24T02:09:28.967 に答える
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'
于 2009-07-24T01:20:40.153 に答える
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

お役に立てば幸いです

于 2013-02-16T17:58:52.753 に答える
1

正規表現を使用した恐ろしい例 (これは簡単に片付けることができます :) ):

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

編集:アンダースコアが無条件に挿入されるため、「テスト」のような場合には改善の余地があることも簡単にわかるはずです。

于 2009-07-24T02:05:16.663 に答える
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()
  • 任意の数の (またはゼロの) 大文字が前にあり、任意の数の小文字が後に続く大文字を探します。
  • アンダースコアは、グループ内で見つかった最後の大文字の直前に配置され、他の大文字が先行する場合に備えて、その大文字の前に配置できます。
  • 末尾にアンダースコアがある場合は、それらを削除します。
  • 最後に、結果の文字列全体が小文字に変更されます。

ここから取得、オンラインの実例を参照)

于 2015-11-04T08:06:03.690 に答える
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')
于 2016-04-01T13:30:43.327 に答える
0

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

ステップ 1...小文字が前にある大文字または整数を見つけ、それらの前にアンダースコアを付けます。

探す:

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

置換:

\1_\l\2/

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

探す:

([A-Z])

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

\l\1
于 2011-12-09T22:41:32.203 に答える
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
于 2015-08-27T14:27:01.313 に答える
0

このサイトで提案された非常に素晴らしい正規表現:

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

PythonにString Splitメソッドがある場合、それは機能するはずです...

Java の場合:

String s = "loremIpsum";
words = s.split("(?&#60;!^)(?=[A-Z])");
于 2011-09-29T07:19:31.850 に答える
0

うわー、これをジャンゴのスニペットから盗んだところです。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'

正規表現のデモ

于 2011-03-18T19:05:44.833 に答える
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))
于 2018-03-18T15:29:31.950 に答える
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"))

もちろん、他のソリューションで説明したように、正規表現をプリコンパイルするか、ハイフンの代わりにアンダースコアで結合することができます。

于 2013-01-31T20:55:29.483 に答える
-1

標準ライブラリにはありませんが、必要な機能が含まれているように見えるこのモジュールを見つけました。

于 2009-07-24T00:27:58.027 に答える
-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)
于 2012-06-11T18:17:16.580 に答える
-2
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()
于 2018-01-06T05:18:27.950 に答える
-5

使用:str.capitalize()文字列 (変数 str に含まれる) の最初の文字を大文字に変換し、文字列全体を返します。

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

于 2015-08-18T06:07:33.170 に答える