Итерация по строке в кусках разных размеров python - PullRequest
0 голосов
/ 05 июля 2018

Так что я работаю с файлами в python, чувствую, что есть имя для них, но я не уверен, что это такое. Они похожи на CSV-файлы, но без разделителя. В любом случае, в моем файле много строк данных, где первые 7 символов - это идентификационный номер, а следующие 5 - что-то еще и так далее. Поэтому я хочу просмотреть файл, прочитав каждую строку, разделив его и сохранив в виде списка. Вот пример:

Из файла: "0030108102017033119080001010048000000"

Это чанки, на которые я хотел бы разбить строку: [7, 2, 8, 6, 2, 2, 5, 5] Каждое число представляет длину каждого чанка.

Сначала я попробовал это:

n = [7, 2, 8, 6, 2, 2, 5, 5]
for i in range(0, 37, n):
    print(i)

Естественно, это не сработало, так что теперь я начал думать о возможных методах, и все они кажутся довольно сложными. Я смотрел в Интернете и не мог найти ничего, только куски размером. Так какой-нибудь вклад?

РЕДАКТИРОВАТЬ: Ответ, который я ищу, должен в этом случае выглядеть следующим образом: ['0030108', '10', '20170331', '190800', '01', '01', '00480', '00000'] Где каждое значение в списке n представляет длину каждого чанка.

Ответы [ 4 ]

0 голосов
/ 05 июля 2018
from itertools import accumulate, chain
s = "0030108102017033119080001010048000000"
n = [7, 2, 8, 6, 2, 2, 5, 5]
ranges = list(accumulate(n))
list(map(lambda i: s[i[0]:i[1]], zip(chain([0], ranges), ranges))
# ['0030108', '10', '20170331', '190800', '01', '01', '00480', '00000']
0 голосов
/ 05 июля 2018

Не могли бы вы попробовать это?

for line in file:
    n = [7, 2, 8, 6, 2, 2, 5, 5]
    total = 0
    for i in n:
        print(line[total:total+i])
        total += i 

Вот как я мог это сделать. Код перебирает каждую строку в файле, и для каждой строки перебирает список длин, которые вам нужно вытащить, который находится в списке n. Это может быть изменено, чтобы сделать что-то еще вместо печати, но идея в том, что срез возвращается из строки. Переменная total отслеживает, насколько далеко мы находимся в строках.

0 голосов
/ 05 июля 2018

Если это строки ASCII (точнее, один байт на символ), я мог бы использовать struct.unpack для этого.

>>> import struct
>>> sizes = [7, 2, 8, 6, 2, 2, 5, 5]
>>> struct.unpack(''.join("%ds" % x for x in sizes), "0030108102017033119080001010048000000")
('0030108', '10', '20170331', '190800', '01', '01', '00480', '00000')
>>>

В противном случае вы можете построить необходимые slice объекты из частичных сумм размеров, что легко сделать, если вы используете Python 3:

>>> psums = list(itertools.accumulate([0] + sizes))
>>> [s[slice(*i)] for i in zip(psums, psums[1:])]
['0030108', '10', '20170331', '190800', '01', '01', '00480', '00000']

accumulate может быть реализовано в Python 2 с чем-то вроде

def accumulate(itr):
    total = 0
    for x in itr:
        total += x
        yield total
0 голосов
/ 05 июля 2018

Вот генератор, который возвращает чанки путем итерации символов lsit и формирования из них подстрок. Вы можете использовать это, чтобы обработать любую итерацию таким образом.

def chunks(s, sizes):
    it = iter(s)
    for size in sizes:
        l = []
        try:
            for _ in range(size):
                l.append(next(it))
        finally:
            yield ''.join(l)

s="0030108102017033119080001010048000000"
n = [7, 2, 8, 6, 2, 2, 5, 5]
print(list(chunks(s, n)))
# ['0030108', '10', '20170331', '190800', '01', '01', '00480', '00000']
...