[英]How to get the first capital letter and then each that isn't followed by another capital letter in Python?
我正在开发一个脚本,该脚本为一个我无法使用的名称列表创建缩写。 我需要将每个名称分成多个点,然后将每个大写字母都放在单词的开头。 像这样:
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
您可以为此使用正则表达式。 例如,您可以对要保留的字符使用捕获组,并在仅保留那些捕获的字符的地方执行替换:
import re
def shorten(s):
return re.sub(r'([A-Z])(?:[A-Z]*(?=[A-Z])|[^A-Z.]*)|\.(\d+)[^A-Z.]*', r'\1\2', s)
说明:
([AZ])
:大写字母 (?: )
:):这是一个分组,以明确|
范围是什么|
里面的操作。 这不是上面的捕获组(因此将被删除) [AZ]*
:零个或多个大写字母(贪心) (?=[AZ])
:应该再加上一个大写字母,但不要对其进行处理-留给下一场比赛 |
:逻辑或 [^AZ.]*
:零个或多个非大写非点数(紧随大写字母之后):这些将被删除 \\.(\\d+)
:一个文字点后跟一个或多个数字:捕获数字(以丢弃点)。 在替换参数中,捕获的组再次注入:
\\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
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
正则表达式包含三个主要部分:
(?<![AZ])[AZ]
或 [AZ](?![AZ])
后没有大写字母,则匹配
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.