关于python:使用索引替换字符串元素的字符串元素

Replace string elements, using their index, by a list of strings

我必须构建的函数是用(数字值*下一个字符)替换字符串中的数字。

因此,foo = '2 hs4q q2w2 '将成为' hsqqqq qww '(注意空间)

假设-数字不能为零。

我提取了数字和下一个字符的(索引、值)。使用该信息获取需要放回字符串中的子字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
foo = '2 hs4q q2w2 '

parameters=[(int(foo_list[b]),b+1) for b in range(len(foo_list)) if foo_list[b].isdigit()]
parameters # list of tuples (digit,charindex to be extended)
#[(2, 1), (4, 5), (2, 9), (2, 11)]

for p,i in parameters:
    hoo=p*foo[i]
    print (hoo,type(hoo))

 #Out
   <class 'str'> # Two spaces
qqqq <class 'str'>
ww <class 'str'>
   <class 'str'> # Two spaces

如何在使用类似字符串的循环中使用所有这些信息?我知道字符串是不可变的,因此必须为每个插入/替换创建一个新的str对象。另外,索引值随着循环的运行而变化。

解决方案后的注释-

感谢大家提供四种不同的解决方案,这里是一个参考资料,供没有使用过yield from, yield的人参考。在实践中,python 3.3中新的"yield-from"语法的主要用途是什么?


单位数

您可以检查字符是否是带str.isdigit的数字,如果是,则将其转换为带int的数字,并将其与下一个字符相乘。这个逻辑可以写成一个给定给str.join的生成器。

代码

1
2
def expand_string(s):
    return ''.join([(int(c) - 1) * s[i+1] if c.isdigit() else c for i, c in enumerate(s)])

例子

1
2
foo = '2 hs4q q2w2 '
print(expand_string(foo)) # '  hsqqqq qww  '

但是,对于具有多个数字的字符串(如f10o')则上述操作失败。

多位数

如果还想考虑具有多个数字的数字,可以使用itertools.groupby编写一个将数字分组在一起的生成器函数。

代码

1
2
3
4
5
6
7
8
9
from itertools import groupby

def group_digits(s):
    for isdigit, group in groupby(s, str.isdigit):
        yield from [''.join(group)] if isdigit else group

def expand_string(s):
    s = list(group_digits(s))
    return ''.join((int(c) - 1) * s[i+1] if c.isdigit() else c for i, c in enumerate(s))

例子

1
2
foo = 'f10o'
print(expand_string(foo)) # 'foooooooooo'

您可以使用re.sub

1
2
3
import re
foo = '2 hs4q q2w2 '
new_foo = re.sub('\d+[\w\W]{1}', lambda x:x.group()[-1]*int(x.group()[:-1]), foo)

输出:

1
'  hsqqqq qww  '


在当前迭代中使用下一个索引时要小心,因为如果字符串类似于foo='2 hs4q q2w2 2'使用Try和Except

1
2
3
4
5
6
7
8
9
10
11
12
foo = '2 hs4q q2w2 '

splitted_data=list(foo)

for i,j in enumerate(splitted_data):
    try:
        if j.isdigit():
            splitted_data[i]=splitted_data[i+1]*int(j)
    except IndexError:
        pass

print("".join(splitted_data))

输出:

1
   hsqqqqq qwww

一种方法是使用zipitertools.zip_longest迭代字符串对中的字符,并根据字符是否为数字生成一个项目。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from itertools import zip_longest, islice

foo = '2 hs4q q2w2 '

def gen(x):
    for i, j in zip_longest(x, islice(x, 1, None), fillvalue=''):
        if i.isdigit():
            yield j * (int(i)-1)
        else:
            yield i

res = ''.join(list(gen(foo)))

# '  hsqqqq qww  '

这种函数可以通过while循环获得:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def new_string(string):
    # Create the variable new_string
    new_string =""
    i = 0
    while i < len(string):
        char = string[i]
        # If char is a digit we multiply the next char by it
        if char.isdigit():
            new_string += int(char)*string[i+1]
            i += 2
        # If not we just concatenate char
        else:
            new_string += char
            i += 1
    return new_string

希望它有帮助。