4

Имеется текстовый файл с данным содержанием "D11i14V17A8n7R11H16r18P18E5h18i18x8O16Y5s13d1X6u4a20C2p2O14J5I11L5K6y4X19n10s17h1E17Q5Z1U1K6U8E8L11n14k6". Я написал код который разделяет буквенные значения в один список, цифровые в другой. Как правильно перемножить данные из списка, чтобы в конечном итоге получилось D * 11 = DDDDDDDDDDD (Буква D 11 раз). Код ниже:

import re
c = []
d = []
result = 0
with open('dest.txt', 'r') as s:
    for line in s:
        line = line.strip()
        lst = re.split('(\d*)', line)

        for i in lst:
            if i.isalpha() == True:
                c.append(i)
            else:
                d.append(i)

for a, b in zip(c, d): 
     result += a*b

print(result)

Результат:

D:\Python\lib\re.py:212: FutureWarning: split() requires a non-empty pattern match.
  return _compile(pattern, flags).split(string, maxsplit)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-22-24c875dcd30e> in <module>()
     16 
     17 for a, b in zip(c, d):
---> 18      result += a*b
     19 
     20 print(result)

TypeError: can't multiply sequence by non-int of type 'str'
Jemale
  • 306
  • Вроде [a] * b – diralik Sep 13 '17 at 15:40
  • К сожалению такой способ не работает. Ошибка продолжает выходить. – Jemale Sep 13 '17 at 15:47
  • 1
    А какой должен получиться result для строки A2B3 ­— AABBB? Почему тогда в начале переменной result присваивается ноль (не пустая строка, не пустой массив, а именно ноль)?) – diralik Sep 13 '17 at 16:10
  • Немного переиначил код, но спасибо за подсказку. Действительно надо в result добавить пустую строку. Огромное спасибо! – Jemale Sep 13 '17 at 16:16

3 Answers3

6
In [20]: import re

In [21]: task = "D11i14V17A8n7R11H16r18P18E5h18i18x8O16Y5s13d1X6u4a20C2p2O14J5I11L5K6y4X19n10s17h1E17Q5Z1U1K6
    ...: U8E8L11n14k6"

In [22]: numbers, lit = list(re.findall(r'\d+', task)), list(re.findall(r'\D', task))

In [23]: ''.join(int(x) * y for x, y in zip(numbers, lit))

Результат:

Out[25]: 'DDDDDDDDDDDiiiiiiiiiiiiiiVVVVVVVVVVVVVVVVVAAAAAAAAnnnnnnnRRRRRRRRRRRHHHHHHHHHHHHHHHHrrrrrrrrrrrrrrrrrrPPPPPPPPPPPPPPPPPPEEEEEhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiixxxxxxxxOOOOOOOOOOOOOOOOYYYYYsssssssssssssdXXXXXXuuuuaaaaaaaaaaaaaaaaaaaaCCppOOOOOOOOOOOOOOJJJJJIIIIIIIIIIILLLLLKKKKKKyyyyXXXXXXXXXXXXXXXXXXXnnnnnnnnnnssssssssssssssssshEEEEEEEEEEEEEEEEEQQQQQZUKKKKKKUUUUUUUUEEEEEEEELLLLLLLLLLLnnnnnnnnnnnnnnkkkkkk'
5

Чтобы распаковать файл/обратить кодирование длин серий (RLE), удобно использовать re.split(), чтобы отделить символы от цифр, и zip(), чтобы попарно их обойти:

import re
from pathlib import Path 

rle_tokens = iter(re.split(r'(\d+)', Path('rle.txt').read_text()))
decompressed = ''.join([char * int(digits) for char, digits in zip(rle_tokens, rle_tokens)])
print(decompressed)

Объяснение как zip(it, it) работает.

Результат:

DDDDDDDDDDDiiiiiiiiiiiiiiVVVVVVVVVVVVVVVVVAAAAAAAA...
jfs
  • 52,361
  • Зачем квадратные скобки в join() ? – Pavel Durmanov Sep 13 '17 at 17:04
  • 1
    @Alban чтобы список создать. Если список (последовательность) не передать, ''.join изнутри сам список создаёт (лишний раз строки обходит). Строго говоря, это преждевременная оптимизация, так что дело вкуса со скобками или без писать. – jfs Sep 13 '17 at 17:13
2

Вот так переделал код. Надо было присвоить result пустую строку.

import re
c = []
d = []
result = ''
with open('dest.txt', 'r') as s:
    for line in s:
        line = line.strip()
        lst = re.split('(\d+)', line)

        for i in lst:
            if i.isalpha() == True:
                c.append(i)
            else:
                d.append(i)

for a, b in zip(c, d):
    str(a) * int(b)
    result += str(a) * int(b)


print(result)
Jemale
  • 306
  • 1
    Ещё замечу, что лучше делать split по \d+, а не по \d*, так как в последнем случае под регулярное выражение подходит пустая строка, а это вроде плохо (у меня, например, warning выдаётся) – diralik Sep 13 '17 at 16:21
  • 1
    И ещё цикл for i in lst: можно заменить на c = lst[::2], d = lst[1::2] – diralik Sep 13 '17 at 16:23
  • Совершенно верно, лучше использовать \d+ иначе выдается предупреждение, только обозначено оно предупреждением на будущее. – Jemale Sep 13 '17 at 19:10