Format string height

Есть список строк взятый из файла:

data = ["Это текст имеет 27 символов", "Этот 16 символов", "а этот и сразу содержит 35 символов"]

Задача состоим втом чтобы отформатировать текст таким образом чтобы строка была растянута по ширине, заданной в count.

count = int(input())
out = []
for i in data:
    out.append(i.center(35))
print(out)

При таком коде я получаю:

      Это текст имеет 27 символов   
            Этот 16 символов          

А хочу получать:

Это   текст   имеет   27   символов
Этот           16          символов

Ответы (2 шт):

Автор решения: GrAnd

Разбить строку на слова, подсчитать требуемое количество пробелов в каждом промежутке, слить слова с пробелами. Profit.

def justify(s, maxlen):
    def spaces(l, n): # вычисляет нужное количество пробелов в каждом промежутке
        # l - требуемое общее количество пробелов
        # n - количество мест (промежутков между словами)
        seq = [round(l/n)]
        for i in range(2, n+1):
            seq.append(round(l*i/n) - sum(seq))
        return list(map(lambda x: " "*x, seq))

    s = s.strip()
    if len(s) >= maxlen:
        return s

    words = s.split(" ")
    if len(words) < 2:
        return s.center(maxlen)
    
    return "".join(sum(zip(words, spaces(maxlen - sum(map(len, words)), len(words)-1) + [""]), ()))

data = ["Это текст имеет 27 символов", 
        "Этот 16 символов", 
        "а этот и сразу содержит 35 символов"]
for t in data:
    r = justify(t, 35)
    print(r, "=>", len(r))
Это   текст   имеет   27   символов => 35
Этот          16           символов => 35
а этот и сразу содержит 35 символов => 35

Вариант алгоритма как у @Рамис (пробелы распределены не равномерно, а слева больше), но вообще без использования циклов.

def justify(s, maxlen):
    s = s.strip()

    if len(s) >= maxlen:
        return s

    space_count = s.count(' ');
    if not space_count:
        return s.center(maxlen)

    total_spaces = maxlen - len(s) + space_count
    min_spaces = total_spaces // space_count

    words  = s.split(' ', round((total_spaces / space_count - min_spaces) * space_count))
    words[-1] = words[-1].replace(' ', ' '*min_spaces)

    return (' '*(min_spaces+1)).join(words)
→ Ссылка
Автор решения: Рамис

Создаем список space_index с индексом каждого пробела в строке.

space_index = [index for index, char in enumerate(text) if char == ' ']

В строке, рядом с индексом пробела space_index[i] добавляем новый пробел.

text = text[:space_index[i]] + ' ' + text[space_index[i]:]

Изменяем список с индексом пробелов, так как тест изменился.

space_index = space_index[:i]+list(map(lambda x: x+1, space_index[i:]))

Выполняем это пока строка не станет длинной в 35 символов.

def my_func(data, count=35):
    for text in data:
        space_index = [index for index, char in enumerate(text) if char == ' ']
        i = 0
        while True:
            if len(text) < count and len(space_index) > 0:
                text = text[:space_index[i]] + ' ' + text[space_index[i]:]
                space_index = space_index[:i]+list(map(lambda x: x+1, space_index[i:]))
                i+=1
                if i+1 > len(space_index):
                    i = 0
            else:
                break
        print(text)

data = ["Это текст имеет 27 символов", "Этот 16 символов", "а этот и сразу содержит 35 символов", "aaaaaaaa"]
my_func(data, 35)

Ответ:

Это   текст   имеет   27   символов
Этот           16          символов
а этот и сразу содержит 35 символов
aaaaaaaa
→ Ссылка