如何获得第一个大写字母,然后是每个不在Python中的另一个大写字母?

时间:2018-03-01 12:55:32

标签: python python-3.x

我正在开发一个脚本,该脚本为名称列表创建缩写,这些名称对我来说太长了。我需要将每个名称拆分成除以点的部分,然后将每个大写字母分成一个单词的开头。就像这样:

InternetGatewayDevice.DeviceInfo.Description - >的 IGD.DI.D

但是,如果有更多连续的大写字母(如下例所示),我只想采用第一个一个,然后是的那个用大写字母。所以,来自" WANDevice "我想得到" WD "。像这样:

InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.PortMapping.7.ExternalPort - > IGD.WD1.WCD1.WC1.PM7.EP

到目前为止,我已经编写了这个脚本:

data = json.load(open('./cwmp/tr069/test.json'))

def shorten(i):
    x = i.split(".")
    abbreviations = []
    for each in x:
        abbrev = ''
        for each_letter in each:
            if each_letter.isupper():
                abbrev = abbrev + each_letter
        abbreviations.append(abbrev)
    short_string = ".".join(abbreviations)
    return short_string

for i in data["mappings"]["cwmp_genieacs"]["properties"]:
    if "." in i:
        shorten(i)
    else:
        pass    

它正常工作"翻译"第一个例子,但我不知道如何做其余的事情。我想如果必须的话,我可能会想到一些的方式(比如将字符串分成单个字符),但我正在寻找一个高效的&聪明的方式来做到这一点。我会很感激任何建议。

我正在使用Python 3.6。

修改

我决定尝试不同的方法并迭代单个字符,我很容易实现我想要的。不过,谢谢你的答案和建议,我一定会仔细阅读。

def char_by_char(i):
    abbrev= ""
    for index, each_char in enumerate(i):
        # Define previous and next characters 
        if index == 0:
            previous_char = None
        else:
            previous_char = i[index - 1]

        if index == len(i) - 1:
            next_char = None
        else:
            next_char = i[index + 1]
        # Character is uppercase
        if each_char.isupper():
            if next_char is not None:
                if next_char.isupper():
                    if (previous_char is ".") or (previous_char is None):
                        abbrev = abbrev + each_char
                    else:
                        pass
                else:
                    abbrev = abbrev + each_char
            else:
                pass
        # Character is "."
        elif each_char is ".":
            if next_char.isdigit():
                pass
            else:
                abbrev = abbrev + each_char

        # Character is a digit              
        elif each_char.isdigit():
            abbrev = abbrev + each_char

        # Character is lowercase            
        else:
            pass
    print(abbrev)


for i in data["mappings"]["cwmp_genieacs"]["properties"]:
    if "." in i:
        char_by_char(i)
    else:
        pass    

3 个答案:

答案 0 :(得分:3)

您可以使用正则表达式。例如,您可以将捕获组用于要保留的字符,并执行替换,只保留捕获的字符:

import re

def shorten(s):
    return re.sub(r'([A-Z])(?:[A-Z]*(?=[A-Z])|[^A-Z.]*)|\.(\d+)[^A-Z.]*', r'\1\2', s)  

说明:

  • ([A-Z]):捕获大写字母
  • (?: ):这是一个分组,用于明确其中|操作的范围。这不是上面的捕获组(所以这将被删除)
  • [A-Z]*:零个或多个大写字母(贪婪)
  • (?=[A-Z]):应该跟随一首大写字母,但不要处理它 - 留待下一场比赛
  • |:逻辑或
  • [^A-Z.]*:零个或多个非大写字母,非点数(跟随捕获的大写字母):这些将被删除
  • \.(\d+):一个字面点后跟一个或多个数字:捕获数字(为了丢弃点)。

在替换参数中,再次注入捕获的组:

  • \1:第一个捕获组(这是大写字母)
  • \2:第二个捕获组(这些是跟在点后面的数字)

在一场比赛中,只有一个捕获组会有一些东西,另一个只是空字符串。但是在整个输入字符串中重复正则表达式匹配。

答案 1 :(得分:2)

这是一个非正则表达式解决方案。

def shorten(i):
    abr_list = []
    abrev = ''
    parts = i.split('.')
    for word in parts:
        for x in range(len(word)):
            if x == 0 and word[x].isupper() or word[x].isupper() and not word[x + 1].isupper() or word[x].isnumeric():
                abrev += word[x]
        abr_list.append(abrev)
        abrev = ''
    return join_parts(abr_list)


def join_parts(part_list):
    ret = part_list[0]
    for part in part_list[1:]:
        if not part.isnumeric():
            ret += '.%s' % part
        else:
            ret += part
    return ret

答案 2 :(得分:1)

import re
def foo(s):
    print(''.join(list(map(
        lambda matchobj: matchobj[0], re.finditer(
            r'(?<![A-Z])[A-Z]|[A-Z](?![A-Z])|\.', s)))))
foo('InternetGatewayDevice.DeviceInfo.Description')
foo('WANDevice')
# output: 
# IGD.DI.D
# WD

正则表达式有三个主要部分:

  1. 匹配,如果它是大写字母,前面没有大写字母(?<![A-Z])[A-Z]
  2. 匹配,如果是[A-Z](?![A-Z])
  3. 之后没有大写字母的大写字母
  4. 如果是文字句号
  5. https://docs.python.org/3.6/library/re.html