如何在字符串中累积一系列数字并将它们转换为一个数字?

问题描述 投票:4回答:6

我需要将字符串'a3b2'解码为'aaabb'。问题是数字是双倍,三位数。例如。 'a10b3'应检测到该数字不是1而是10。

我需要开始累积数字。

a = "a12345t5i6o2r43e2"
for i in range(0, len(a)-1):
  if a[i].isdigit() is False: 
   #once i see a letter, i launch a while loop to check how long a digit streak

   #after it can be - it's 2,3,4,5 digit number etc
    print(a[i])
    current_digit_streak = ''
    counter = i+1
    while a[counter].isdigit():  #this gives index out of range error!
      current_digit_streak += a[counter]
      counter+=1

如果我将while循环更改为:

while a[counter].isdigit() and counter < ( len(a)-1)

它确实有效,但省略了最后一封信。我不应该使用正则表达式,只能使用循环。

python string
6个回答
1
投票

你的for循环和while循环使用不同的索引来获得令牌,这就是while循环再次处理for循环消耗的字符的原因。您应该使用带有单个索引的while循环来解析标记:

a = "a12t5i6o2r11e2"
i = 0
char = repeat = output = ''
while i < len(a):
    token = a[i]
    if token.isdigit():
        repeat += token
    if char and repeat and (not token.isdigit() or i == len(a) - 1):
        output += char * int(repeat)
        char = repeat = ''
    if not token.isdigit():
        char += token
    i += 1
print(output)

这输出:

aaaaaaaaaaaatttttiiiiiioorrrrrrrrrrree

3
投票

正则表达式非常适合这里。

import re
pat = re.compile(r"""
(\w)       # a word character, followed by...
(\d+)      # one or more digits""", flags=re.X)

s = "a12345t5i6o2r43e2"
groups = pat.findall(s)
# [('a', '12345'), ('t', '5'), ('i', '6'), ('o', '2'), ('r', '43'), ('e', '2')]

result = ''.join([lett*int(count) for lett, count in groups])

由于您不能使用正则表达式出于某些未知的原因,我建议使用递归函数将字符串拆分为多个部分。

import itertools

def split_into_groups(s):
    if not s:
        return []
    lett, *rest = s
    count, rest = int(itertools.takewhile(str.isdigit, rest)), itertools.dropwhile(str.isdigit, rest)
    return [(lett, count)] + split_into_groups(rest)

s = "a12345t5i6o2r43e2"
groups = split_into_groups(s)

result = ''.join([lett*count for lett, count in groups])

或者,使用更通用(和功能派生)模式:

def unfold(f, x):
    while True:
        v, x = f(x)
        yield v

def get_group(s):
    if not s:
        raise StopIteration()
    lett, *rest = s
    count, rest = int(itertools.takewhile(str.isdigit, rest)), itertools.dropwhile(str.isdigit, rest)
    return lett*count, rest

s = "a12345t5i6o2r43e2"
result = ''.join(unfold(get_group, s))

2
投票

你可以使用groupby

from itertools import groupby

text = 'a12345t5i6o2r43e2'

groups = [''.join(group) for _, group in groupby(text, key=str.isdigit)]
result = list(zip(groups[::2], groups[1::2]))

print(result)

产量

[('a', '12345'), ('t', '5'), ('i', '6'), ('o', '2'), ('r', '43'), ('e', '2')]

1
投票

可能的变种之一

import re


def main():
    a = "a10t5i6o2r43e2"
    items = re.findall(r'(\w)(\d+)', a)
    return ''.join([letter*int(count) for letter, count in items])

1
投票

这是使用itertools模块的功能解决方案。您可以使用grouper recipe from the itertools docs或通过第三方more_itertools.grouper导入:

from itertools import groupby
from more_itertools import grouper
from operator import itemgetter

a = "a12t5i6o2r11e2"

it = map(''.join, map(itemgetter(1), groupby(a, key=str.isdigit)))

res = ''.join(char*int(count) for char, count in grouper(it, 2))

'aaaaaaaaaaaatttttiiiiiioorrrrrrrrrrree'

供参考,grouper食谱:

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

1
投票

这有点冗长,但它可以按照您的要求工作并使用循环:

def parse_segment(string, index):
    for i, letter in enumerate(string[index+1:]):
        if letter.isalpha():
            return string[index+1:i+index+1]
        if i + index + 1 >= len(string) - 1:
            return string[index+1:]

def segment_string(string):
    num_list = []
    for index, letter in enumerate(string):
        if letter.isalpha():
            num_list.append({'letter': letter, 'number': int(parse_segment(string,  index))})
    return num_list

def list_2_string(list):
    ret_string = ''
    for row in list:
        ret_string += row['letter'] * row['number']
    return ret_string

a = "a12345t5i6o2r43e2"
segmented_string = segment_string(a)
result_string = list_2_string(segmented_string)
print(result_string)
© www.soinside.com 2019 - 2024. All rights reserved.