нулевое заполнение пустых мест в определенных местах

#python

#python

Вопрос:

У меня есть небольшой вопрос. У меня есть файл в следующем формате:

 1 2 
1 2 3
1 2
1 2 3 4
2 4
  

Значения в коде на самом деле представляют числа (не обязательно однозначные), но они могут быть любыми числами, также могут быть значениями с плавающей запятой.

Входной файл: Для конкретной строки каждое число отделено от другого одним пробелом (разделителем не может быть ничего, кроме пробела).

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

 1 2 0 0
1 2 3 0
1 2 0 0
1 2 3 4
2 4 0 0
  

Выходной файл: Применяется то же правило. Для конкретной строки каждое число отделяется от другого только одним пробелом.

Используемый язык: Python (или может быть Shell, если это возможно)

Я знаю, что есть такая функция, которая называется zfill, но я не думаю, что это сильно помогло бы мне.

Мое решение: найдите (максимальную длину / 2) каждой строки, используя функции len и max. Затем, используя split(), заполните нулями соответствующие места каждой строки. Я боюсь, что это может превратиться в грязный код, и я уверен, что есть лучшие способы выполнить эту задачу.

Любое предложение приветствуется.

Спасибо!

Комментарии:

1. все ли числа в файлах однозначные?

2. Вам нужно быть более конкретным. Действительно ли значения 1 , 2 3 , 4 ,,,,,,,,,,, на самом деле представляют числа (т. Е. Они могут быть любыми), или они являются каким-то символом, концептуально обрабатываемым как символ (т. Е. Это всегда будет только одна цифра каждое)? Может ли пробел во входных данных, разделяющий их, быть чем-то иным, кроме пробелов? Имеет ли значение, как они расположены в выходном файле?

3. @Karl Knechtel: Я попытался ответить на ваши вопросы, обновив свой первоначальный вопрос. Пожалуйста, дайте мне знать, если вам нужны дополнительные сведения.

Ответ №1:

Предположим, myfile это открытый файл. Мы используем izip_longest из itertools для перебора столбцов входного файла, заполняя "0" отсутствующие значения:

 [('1', '1', '1', '1', '2'),  ('2', '2', '2', '2', '4'),      
 ('0', '3', '0', '3', '0'), ('0', '0', '0', '4', '0')]
  

Затем мы просто снова заархивируем этот вывод, чтобы восстановить строки с заполненными нулями. Это код:

 from itertools import izip_longest

rows = [line.split() for line in myfile]            # Read
rows = zip(*izip_longest(*rows, fillvalue="0"))     # Add zeroes
print "n".join(" ".join(row) for row in rows)      # Write
  

РЕДАКТИРОВАТЬ: приведенное выше (имхо элегантное) решение немного медленнее (8,55 usec против 7,08 usec), чем наивный подход:

 rows = [line.split() for line in myfile]
maxlen = max(len(x) for x in rows)
for row in rows:
    print " ".join(row   ["0"] * (maxlen - len(row)))
  

Повторный комментарий

Если вы хотите выровнять столбцы, проще всего изменить первый подход, потому что там у нас уже есть числа, упорядоченные по столбцам в одной точке. Это упрощает поиск ширины столбца.

 from itertools import izip_longest

rows = [line.split() for line in myfile]
columns = list(izip_longest(*rows, fillvalue="0"))
column_width = [max(len(num) for num in col) for col in columns]

# We make a template of the form "{0:>a} {1:>b} {2:>c} ...",
# where a, b, c, ... are the column widths:
column_template = "{{{0}:>{1}s}}"
row_template = " ".join(column_template.format(i, n) for
    i, n in enumerate(column_width))

print "n".join(row_template.format(*row) for row in zip(*columns))
  

Комментарии:

1. Спасибо. Если я не ошибаюсь, ваше решение кажется прекрасным, если столбцы представляют собой однозначные числа. Но, как я уже упоминал, в этом нет необходимости. Если во входном файле есть двузначное / многозначное число в любом из его столбцов, выходные данные, которые предоставляет ваш код, довольно беспорядочные, т. Е. они не находятся (или, скорее, не начинаются / заканчиваются) в одном столбце. Подумайте об этом так: выходные данные, следовательно, сгенерированные, берутся как матрица для дальнейших матричных операций. Для меня это не проблема, поскольку genfromtxt, похоже, позаботится об этом (по крайней мере, на данный момент). Итак, я поднимаю это только для целей обсуждения

2. Позвольте мне процитировать вам ваш вопрос: «Выходной файл: применяется то же правило. Для конкретной строки каждое число отделяется от другого только одним пробелом «. Вы передумали?

3. Да, я виноват. Посмотрев на вывод многозначных столбцов, мне пришлось изменить свое мнение.

Ответ №2:

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

Чтобы подсчитать количество чисел, которые вы можете использовать str.split() с вашим символом пробела в качестве разделителя, вы просто получаете количество записей в списке. Добавление вашего номера заполнения должно быть довольно простым.

Дополнительная документация по str.split()

Ответ №3:

Что-то вроде этого — но я также считаю, что его следует обновить, поскольку в вашем вопросе не все ясно:

 tst="""
       1 2
       1 2 3
       1 2
       1 2 3 4
       2 4
    """
res = [line for line in tst.split('n') if line != '']
mLen = max(len(line) for line in res)   
print 'n'.join(list((line   ' 0' * ((mLen - len(line))//2) for line in res)))
  

Комментарии:

1. Вам не нужно использовать list в последней строке: 'n'.join(line ' 0' * ((mLen - len(line))//2) for line in res)

2. @lazyr Конечно, моя ошибка — просто забыл удалить его перед публикацией (играл с итераторами).

3. Спасибо. Если я не ошибаюсь, ваше решение кажется прекрасным, если столбцы представляют собой однозначные числа. Но, как я уже упоминал, в этом нет необходимости. Если во входном файле есть двузначное / многозначное число в любом из его столбцов, выходные данные, которые предоставляет ваш код, довольно беспорядочные, т. Е. они не находятся (или, скорее, не начинаются / заканчиваются) в одном столбце. Подумайте об этом так: выходные данные, следовательно, сгенерированные, берутся как матрица для дальнейших матричных операций. Для меня это не проблема, поскольку genfromtxt, похоже, позаботится об этом (по крайней мере, на данный момент). Итак, я поднимаю это только для целей обсуждения