我有一个像
这样的字符串'A15B7C2'
它代表角色的数量。
我现在正在使用 re 将其拆分为字符和数字。之后,最终将它存储在一个词典中
import re
data_str = 'A15B7C2'
re.split("(\d+)", data_str)
# prints --> ['A', '15', 'B', '7', 'C', '2', '']
但如果我有一个像
这样的字符串'A15B7CD2Ef5'
这意味着C的计数为1(其隐式),Ef的计数为5.(大写和后续的小写计数为一个键)因此我得到了
'CD'= 2(不正确)
'Ef'= 5(正确)
如何修改它以便为我提供正确的计数? 什么是最好的解析方法,并计算和存储在一个字典?
答案 0 :(得分:6)
你可以一举做到这一切:
In [2]: s = 'A15B7CD2Ef5'
In [3]: {k: int(v) if v else 1 for k,v in re.findall(r"([A-Z][a-z]?)(\d+)?", s)}
Out[3]: {'A': 15, 'B': 7, 'C': 1, 'D': 2, 'Ef': 5}
正则表达式本质上是您的需求的直接翻译,利用.findall
和捕获组:
r"([A-Z][a-z]?)(\d+)?"
基本上,一个大写字母后跟一个小写字母作为第一个组,一个数字可能会或可能不会作为第二个组(如果它不存在,这将返回''
一个棘手的例子:
In [7]: s = 'A15B7CD2EfFGHK5'
In [8]: {k: int(v) if v else 1 for k,v in re.findall(r"([A-Z][a-z]?)(\d+)?", s)}
Out[8]: {'A': 15, 'B': 7, 'C': 1, 'D': 2, 'Ef': 1, 'F': 1, 'G': 1, 'H': 1, 'K': 5}
最后,用一个更棘手的例子来打破它:
In [10]: s = 'A15B7CD2EfFGgHHhK5'
In [11]: re.findall(r"([A-Z](?:[a-z])?)(\d+)?", s)
Out[11]:
[('A', '15'),
('B', '7'),
('C', ''),
('D', '2'),
('Ef', ''),
('F', ''),
('Gg', ''),
('H', ''),
('Hh', ''),
('K', '5')]
In [12]: {k: int(v) if v else 1 for k,v in re.findall(r"([A-Z][a-z]?)(\d+)?", s)}
Out[12]:
{'A': 15,
'B': 7,
'C': 1,
'D': 2,
'Ef': 1,
'F': 1,
'Gg': 1,
'H': 1,
'Hh': 1,
'K': 5}
答案 1 :(得分:2)
您可以使用一些正则表达式逻辑和.span()
:
([A-Z])[a-z]*(\d+)
<小时/>
在Python
中,这将是:
import re
string = "A15B7CD2Ef5"
rx = re.compile(r'([A-Z])[a-z]*(\d+)')
def analyze(string=None):
result = []; lastpos = 0;
for m in rx.finditer(string):
span = m.span()
if lastpos != span[0]:
result.append((string[lastpos], 1))
else:
result.append((m.group(1), m.group(2)))
lastpos = span[1]
return result
print(analyze(string))
# [('A', '15'), ('B', '7'), ('C', 1), ('E', '5')]
答案 2 :(得分:0)
搜索字符串中的字母,而不是数字。
import re
data_str = 'A15B7C2'
temp = re.split("([A-Za-z])", data_str)[1:] # First element is just "", don want that
temp= [a if a != "" else "1" for a in temp] # add the 1's that were implicit in the original string
finalDict = dict(zip(temp[0::2], temp[1::2])) # turn the list into a dict
答案 3 :(得分:0)
与原始逻辑保持一致。我们可以找到所有数字,而不是使用re.split(),在第一个匹配时拆分字符串,保留字符串的后半部分用于下一次拆分,并将这些对存储为元组以供日后使用。
import re
raw = "A15B7CD2Ef5"
# find all the numbers
found = re.findall("(\d+)", raw)
# save the pairs as a list of tuples
pairs = []
# check that numbers where found
if found:
# iterate over all matches
for f in found:
# split the raw, with a max split of one, so that duplicate numbers don't cause more then 2 parts
part = raw.split(f, 1)
# set the original string to the second half of the split
raw = part[1]
# append pair
pairs.append((part[0], f))
# Now for fun expand values
long_str = ""
for p in pairs:
long_str += p[0] * int(p[1])
print pairs
print long_str