我正在开发一个脚本,为一个名字列表创建缩写,这些名称对我来说太长了。我需要将每个名称拆分成除以点的部分,然后将每个大写字母分成一个单词的开头。像这样:
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
这是一个非正则表达式解决方案。
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 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])
:应该跟随一个大写字母,但不要处理它 - 留给下一场比赛|
:逻辑OR[^A-Z.]*
:零个或多个非大写字母,非点数(跟随捕获的大写字母):这些将被删除\.(\d+)
:一个字符后跟一个或多个数字:捕获数字(为了丢弃点)。在替换参数中,再次注入捕获的组:
\1
:第一个捕获组(这是大写字母)\2
:第二个捕获组(这些是跟随点的数字)在一场比赛中,只有一个捕获组会有一些东西,另一个只是空字符串。但是在整个输入字符串中重复正则表达式匹配。
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
正则表达式有三个主要部分:
(?<![A-Z])[A-Z]
或[A-Z](?![A-Z])
或