[英]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.