使用索引替换字符串元素

时间:2018-05-27 00:38:44

标签: python string python-3.x substring

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

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

假设 - 数字不能为零。

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

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 - In practice, what are the main uses for the new “yield from” syntax in Python 3.3?

的任何人的参考资料

5 个答案:

答案 0 :(得分:3)

您可以使用re.sub

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

输出:

'  hsqqqq qww  '

答案 1 :(得分:3)

单个数字

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

代码

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

实施例

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

尽管如此,对于具有多位数字符串的字符串,例如f10o'

,上述操作失败

多位数

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

代码

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))

实施例

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

答案 2 :(得分:1)

一个想法是使用zip(或itertools.zip_longest)成对地迭代字符串中的字符,并根据字符是否为数字生成项目。

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  '

答案 3 :(得分:1)

在当前迭代中使用下一个索引时要小心,它会给你错误,因为如果字符串类似于foo ='2 hs4q q2w2 2'  使用try和except

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))

输出:

   hsqqqqq qwww   

答案 4 :(得分:0)

使用while循环可以获得这样的函数:

#version 420 core

layout(location = 0) out vec3 gPosition;    // Position texel colour
layout(location = 1) out vec3 gNormal;  // Normal texel colour
layout(location = 2) out vec4 gAlbedo;  // Albedo texel colour

in vec3 _texcoord;  
in vec3 _normal;
in vec3 _frag_pos;

uniform bool        type_2d;

uniform sampler2D   albedo;     // Albedo and specular map
uniform samplerCube cubemap;    // Skybox cubemap

vec4 final_colour;

void main()
{

    gPosition = _frag_pos;
    gNormal = normalize(_normal);

    if (type_2d)
    {
        final_colour.rgb = texture(albedo, _texcoord.st).rgb;
        final_colour.a = texture(albedo, _texcoord.st).a;   // Emission
    }
    else
    {
        final_colour.rgb = texture(cubemap, _texcoord).rgb;
        final_colour.a = texture(cubemap, _texcoord).a;
    }

    gAlbedo.rgba = final_colour;
}

希望它有所帮助。