diff --git a/strings/camel_case_to_snake_case.py b/strings/camel_case_to_snake_case.py index 582907be2edb..fe9a843e5ce0 100644 --- a/strings/camel_case_to_snake_case.py +++ b/strings/camel_case_to_snake_case.py @@ -1,60 +1,41 @@ -def camel_to_snake_case(input_str: str) -> str: - """ - Transforms a camelCase (or PascalCase) string to snake_case - - >>> camel_to_snake_case("someRandomString") - 'some_random_string' - - >>> camel_to_snake_case("SomeRandomStr#ng") - 'some_random_str_ng' - - >>> camel_to_snake_case("123someRandom123String123") - '123_some_random_123_string_123' - - >>> camel_to_snake_case("123SomeRandom123String123") - '123_some_random_123_string_123' - - >>> camel_to_snake_case(123) - Traceback (most recent call last): - ... - ValueError: Expected string as input, found - - """ - - # check for invalid input type - if not isinstance(input_str, str): - msg = f"Expected string as input, found {type(input_str)}" - raise ValueError(msg) - - snake_str = "" - - for index, char in enumerate(input_str): - if char.isupper(): - snake_str += "_" + char.lower() - - # if char is lowercase but proceeded by a digit: - elif input_str[index - 1].isdigit() and char.islower(): - snake_str += "_" + char - - # if char is a digit proceeded by a letter: - elif input_str[index - 1].isalpha() and char.isnumeric(): - snake_str += "_" + char.lower() - - # if char is not alphanumeric: - elif not char.isalnum(): - snake_str += "_" - - else: - snake_str += char - - # remove leading underscore - if snake_str[0] == "_": - snake_str = snake_str[1:] - - return snake_str - - -if __name__ == "__main__": - from doctest import testmod - - testmod() +def camel_to_snake(camel_str: str) -> str: + import re + + """ + >>> camel_to_snake('someRandomStringWithNumbers123') + 'some_random_string_with_numbers_1_2_3' + >>> camel_to_snake('someRandomString') + 'some_random_string' + >>> camel_to_snake(123) + Traceback (most recent call last): + ... + ValueError: Expected string as input, found + + """ + + # Raises an error if the input is not a string + if not isinstance(camel_str, str): + msg = f"Expected string as input, found {type(camel_str)}" + raise ValueError(msg) + + """ Use regular expressions to find all occurrences of capital letters + followed by lowercase letters or digits. """ + pattern = re.compile(r"(?<=[a-z0-9])([A-Z0-9])") + + # Replace the capital letter or digit with an underscore and the lowercase version. + snake_str = re.sub(pattern, r"_\1", camel_str) + + # Convert the result to lowercase to get snake_case + snake_str = snake_str.lower() + + # If the string starts with a capital letter, add an underscore at the beginning. + if camel_str[0].isupper(): + snake_str = "_" + snake_str + + return snake_str + + +if __name__ == "__main__": + import doctest + + doctest.testmod()