我正在寻找一种好的,有效的和pythonic的方式来做这样的事情:
('zone1', 'pcomp110007')
到此:
'ZONE 1, PCOMP 110007'
如果可能的话,不使用regex
(除非确实产生了很大的不同......)。因此,将每个字母转换为大写,在字母和数字之间加一个空格,并用逗号连接。
我写的内容如下:
tags = ('zone1', 'pcomp110007')
def sep(astr):
chars = ''.join([x.upper() for x in astr if x.isalpha()])
nums = ''.join([x for x in astr if x.isnumeric()])
return chars + ' ' + nums
print(', '.join(map(sep, tags)))
哪个产生了预期的结果,但看起来有点太多了。
元组的长度可能不同,但数字总是在每个字符串的末尾。
答案 0 :(得分:6)
Regex确实有帮助。这应该始终有效:
import re
tags = ('zone1', 'pcomp110007')
def sep(s):
word = re.split(r'\d', s)[0]
return word.upper() + " " + s[len(word):]
print(', '.join(map(sep, tags)))
答案 1 :(得分:4)
我的想法:
保持sep
正常功能,就像原始代码中的可读性/维护一样,但也可以根据Abdou的回答中的建议使用re
。
import re
tags = ('zone1', 'pcomp110007')
def sep(astr):
alpha, num = re.match('([^\d]+)([\d]+)', astr).groups()
return '{} {}'.format(alpha.upper(), num)
print(', '.join(map(sep, tags)))
编辑:请注意,如果您愿意,我认为回归也是合理的:
return alpha.upper() + ' ' + num
或旧式字符串格式:
return '%s %s' %(alpha.upper(), num)
无论你最满意的是什么。
答案 2 :(得分:3)
使用re
:
import re
tupl = ('zone1', 'pcomp110007')
", ".join(map(lambda x: " ".join(re.findall('([A-Z]+)([0-9])+',x.upper())[0]), tupl))
#'ZONE 1, PCOMP 7'
答案 3 :(得分:2)
我认为你的方式足够pythonic。如果你想让它“更具功能性”,那么你可以使用这个:
sep = lambda s: " ".join((filter(str.isalpha, s).upper(), filter(str.isdigit, s)))
print(', '.join(map(sep, tags)))
更新:它是Python3版本,对于Python2,您需要upper
使用s
,而不是filter
。
答案 4 :(得分:1)
这是我的刺:
>>> for i, s in enumerate(tags[1][::-1]):
... if s.isalpha():
... print (tags[1][:i], tags[1][i:])
break
...
pcomp1 10007
我走回字符串找到第一个字母,然后拆分并打印每一面(字母,数字)。我省略了转换为大写,很容易添加
答案 5 :(得分:1)
递归解决方案:
def non_regex_split(s,i=0):
if len(s) == i:
return s
try:
return '%s %d' %(s[:i], int(s[i:]))
except:
return non_regex_split(s,i+1)
', '.join(non_regex_split(s).upper() for s in tags)
答案 6 :(得分:1)
谢谢大家的答案。我在这里定时了几个结果和时间脚本:
setup = '''
import re
tags = ('zone1', 'pcomp110007')
def sepListComp(astr):
res = ''.join([x.upper() for x in astr if x.isalpha()]), ''.join([x for x in astr if x.isnumeric()])
return '{} {}'.format(*res)
def sepFilter(astr):
res = ''.join(filter(str.isalpha, astr.upper())), ''.join(filter(str.isdigit, astr.upper()))
return '{} {}'.format(*res)
def sepRe1(astr):
alpha, num = re.match('([^\d]+)([\d]+)', astr).groups()
return '{} {}'.format(alpha.upper(), num)
def sepRe2(s):
word = re.split(r'\d', s)[0]
return word.upper() + " " + s[len(word):]
def Recursive(s,i=0):
if len(s) == i:
return s
try:
return '%s %d' %(s[:i], int(s[i:]))
except:
return Recursive(s,i+1)
'''
from timeit import timeit
print('sepListComp:', timeit(stmt='", ".join(map(sepListComp, tags))', setup=setup, number=100000))
print('sepFilter:', timeit(stmt='", ".join(map(sepFilter, tags))', setup=setup, number=100000))
print('sepRe1:', timeit(stmt='", ".join(map(sepRe1, tags))', setup=setup, number=100000))
print('sepRe2:', timeit(stmt='", ".join(map(sepRe2, tags))', setup=setup, number=100000))
print('sepRecursive:', timeit(stmt='", ".join(Recursive(s).upper() for s in tags)', setup=setup, number=100000))
所以regex
获胜。结果虽然有所不同。对时间的任何意见或建议都非常感谢。