2017-08-11 75 views
1

考虑到与数字的字符串:在串数字转换为`_NUM - * _`符号

I counted, ' 1 2 3 4 5 5 5 8 9 10 ' 

的目标是将数字转换为_NUM-*_符号,其中*表示,通过该号码出现顺序。例如。给定上述intpu,期望的输出是:

"I counted, ' _NUM-1_ _NUM-2_ _NUM-3_ _NUM-4_ _NUM-5_ _NUM-6_ _NUM-7_ _NUM-8_ _NUM-9_ _NUM-10_'" 

即使重复数字,例如,给定输入

I said, ' 1 2 3 4 5 5 5 8 9 10 ' 

所需的输出保持数忽略了数字本身例如值的顺序:

"I said, ' _NUM-1_ _NUM-2_ _NUM-3_ _NUM-4_ _NUM-5_ _NUM-6_ _NUM-7_ _NUM-8_ _NUM-9_ _NUM-10_'" 

我已经试过:

import re 

s = "I counted, ' 1 2 3 4 5 6 7 8 9 10 '" 
num_regexp = '(?<!\S)(?=.)(0|([1-9](\d*|\d{0,2}(,\d{3})*)))?(\.\d*[1-9])?(?!\S)' 


re.sub(num_regexp, '_NUM_', s) 

但它只是用相同的_NUM_符号替换输出而不保留顺序,即

[OUT]:

"I counted, ' _NUM_ _NUM_ _NUM_ _NUM_ _NUM_ _NUM_ _NUM_ _NUM_ _NUM_ _NUM_ _NUM_ '" 

我可以做一个后re.sub操作,更换各_NUM_,即

import re 

s = "I counted, ' 1 2 3 4 5 6 7 8 9 10 '" 
num_regexp = '(?<!\S)(?=.)(0|([1-9](\d*|\d{0,2}(,\d{3})*)))?(\.\d*[1-9])?(?!\S)' 

num_counter = 1 
tokens = [] 
for token in re.sub(num_regexp, '_NUM_', s).split(): 
    if token == '_NUM_': 
     token = '_NUM-{}_'.format(num_counter) 
     num_counter += 1 

    tokens.append(token) 

result = ' '.join(tokens) 

[出]:

"I counted, ' _NUM-1_ _NUM-2_ _NUM-3_ _NUM-4_ _NUM-5_ _NUM-6_ _NUM-7_ _NUM-8_ _NUM-9_ _NUM-10_ '" 

是一种更好的方式来实现所需的输出没有先通用re.sub,然后进行事后字符串编辑?

回答

2

使用itertools.count作为传递给re.sub的函数的默认参数。

>>> from itertools import count 

>>> re.sub('(\d+)', lambda m, c=count(1): '_NUM_-{}'.format(next(c)), s) 
' _NUM_-1 _NUM_-2 _NUM_-3 _NUM_-4 _NUM_-5 _NUM_-6 _NUM_-7 _NUM_-8 _NUM_-9 _NUM_-10 ' 

请注意,我使用的是简单的正则表达式匹配数字只是为了演示如何让伯爵,你可以用正则表达式匹配花车以及更换。

+0

酷!我不知道'itertools.count',在替换内部使用lambda表达式超级酷! – alvas