无法通过字符修改正确解析字符串

时间:2019-03-05 18:52:35

标签: python python-3.x string

我遇到了一个问题,我的Python代码没有正确返回旨在在每个大写字母前添加下划线字符的函数调用,而且我不确定我要去哪里。对于输出,仅触摸字符串中的“ courseID”单词,而未触摸其他两个单词。

我以为通过单词中的字母循环,寻找大写字母是行得通的,但事实并非如此。有人可以让我知道我的代码可能在哪里出问题吗?

def parse_variables(string):
    new_string=''
    for letter in string:
        if letter.isupper():
            pos=string.index(letter)
            parsed_string=string[:pos] + '_' + string[pos:]
            new_string=''.join(parsed_string+letter)
        else:
            new_string=''.join(letter)
#        new_string=''.join(letter)
    return new_string.lower()

parse_variables("courseID pathID apiID")

当前输出为单个字母小写d,预期输出应为course_id path_id api_id

3 个答案:

答案 0 :(得分:1)

修改后的代码的问题是index仅在字符串中找到大写字母的第一个出现。由于您重复了相同大写字母的实例,因此该函数永远找不到后续实例。您可以通过简单地串联字母(带或不带下划线)来简化此方法,并避免出现此问题,具体取决于您在迭代时是否使用大写字母。

例如:

def underscore_caps(s):
    result = ''
    for c in s:
        if c.isupper():
            result += f'_{c.lower()}'
        else:
            result += c

    return result

print(underscore_caps('courseID pathID apiID'))
# course_i_d path_i_d api_i_d

或更简洁地使用列表理解和join

def underscore_caps(s):
    return ''.join([f'_{c.lower()}' if c.isupper() else c for c in s])

print(underscore_caps('courseID pathID apiID'))
# course_i_d path_i_d api_i_d

答案 1 :(得分:1)

您的代码有很多问题:

  1. string.index(letter)给出了letter第一次出现的索引,因此如果您有多个,例如Dpos只会更新到第一个的位置。 您可以通过使用enumerate对位置和字母进行迭代来更正此问题,例如for pos, letter in enumerate(string):
  2. 您要在每个大写字母之前加上下划线,即_i_d
  3. 您正在引用string中的parsed_string=string[:pos] + '_' + string[pos:]来覆盖以前的编辑内容

更正所有这些问题:

def parse_variables(string):
    new_string=''
    for pos, letter in enumerate(string):
        if letter.isupper() and pos+1 < len(string) and string[pos+1].isupper():
            new_string += f'_{letter}'
        else:
            new_string += letter
    return new_string.lower()

但是更简单的方法是:

"courseID pathID apiID".replace('ID', '_id')

更新

考虑到要捕获的各种字符串,正则表达式似乎是您要使用的工具:

import re

def parse_variables(string, pattern=r'(?<=[a-z])([A-Z]+)', prefix='_'):
    """Replace patterns in string with prefixed lowercase version.
    Default pattern is any substring of consecutive
    capital letters that occur after a lowercase letter."""

    foo = lambda pat: f'{prefix}{pat.group(1).lower()}'
    return re.sub(pattern, foo, text)

text = 'courseID pathProjects apiCode'
parse_variables(text)

>>> course_id path_projects api_code

答案 2 :(得分:1)

我认为正则表达式解决方案在这里更容易理解。这将以大写字母结尾的单词加上下划线并使它们变为小写

import re

s = "courseID pathID apiID exampleABC DEF"

def underscore_lower(match):
    return "_" + match.group(1).lower()

pat = re.compile(r'(?<=[^A-Z\s])([A-Z]+)\b')

print(pat.sub(underscore_lower, s))
# course_id path_id api_id example_abc DEF

您可能必须使用该正则表达式才能使其完全执行您想要的操作。目前,它会在单词的末尾使用大写字母,而这些单词后面的字符既不是大写字母也不是空格。然后,这些字母变为小写,并在其前面添加下划线。