Search code examples
pythonstringcyclejustify

How to to cycle through a list of white spaces and distribute the white spaces to another list at specific occurrences?


I would like to align-justify a text. For that, I have used Textwrap in order to fit the maximum amount of words per line with a given width. Now, I need to make sure that every single line has occupied the given width (30) by adding white spaces to fill the line with the following criterium: Large gaps go first, then smaller ones ('Lorem--ipsum--dolor--sit-amet,' (2, 2, 2, 1 spaces)).

import textwrap
def justify(text, width):
    max_words_per_line = textwrap.wrap(text, width, break_long_words=False)
    # I am stuck here, I have tried using the cycle module but I cannot make it work 
max_words_per_line = 
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
Vestibulum sagittis dolor
mauris, at elementum ligula
tempor eget. In quis rhoncus
nunc, at aliquet orci. Fusce
at dolor sit amet felis
suscipit tristique. Nam a
imperdiet tellus. Nulla eu
vestibulum urna. Vivamus
tincidunt suscipit enim, nec
ultrices nisi volutpat ac.
Maecenas sit amet lacinia
arcu, non dictum justo. Donec
sed quam vel risus faucibus
euismod. Suspendisse rhoncus
rhoncus felis at fermentum.
Donec lorem magna, ultricies a
nunc sit amet, blandit
fringilla nunc. In vestibulum
velit ac felis rhoncus
pellentesque. Mauris at tellus
enim. Aliquam eleifend tempus
dapibus. Pellentesque commodo,
nisi sit amet hendrerit
fringilla, ante odio porta
lacus, ut elementum justo
nulla et dolor.

I desire:

Lorem  ipsum  dolor  sit amet,
consectetur  adipiscing  elit.
Vestibulum    sagittis   dolor
mauris,  at  elementum  ligula
tempor  eget.  In quis rhoncus
nunc,  at  aliquet orci. Fusce
at   dolor   sit   amet  felis
suscipit   tristique.   Nam  a
imperdiet   tellus.  Nulla  eu
vestibulum    urna.    Vivamus
tincidunt  suscipit  enim, nec
ultrices   nisi  volutpat  ac.
Maecenas   sit   amet  lacinia
arcu,  non dictum justo. Donec
sed  quam  vel  risus faucibus
euismod.  Suspendisse  rhoncus
rhoncus  felis  at  fermentum.
Donec lorem magna, ultricies a
nunc    sit    amet,   blandit
fringilla  nunc. In vestibulum
velit    ac    felis   rhoncus
pellentesque. Mauris at tellus
enim.  Aliquam eleifend tempus
dapibus. Pellentesque commodo,
nisi    sit   amet   hendrerit
fringilla,   ante  odio  porta
lacus,   ut   elementum  justo
nulla et dolor.

Solution

  • data = '''Lorem ipsum dolor sit amet,
    consectetur adipiscing elit.
    Vestibulum sagittis dolor
    mauris, at elementum ligula
    tempor eget. In quis rhoncus
    nunc, at aliquet orci. Fusce
    at dolor sit amet felis
    suscipit tristique. Nam a
    imperdiet tellus. Nulla eu
    vestibulum urna. Vivamus
    tincidunt suscipit enim, nec
    ultrices nisi volutpat ac.
    Maecenas sit amet lacinia
    arcu, non dictum justo. Donec
    sed quam vel risus faucibus
    euismod. Suspendisse rhoncus
    rhoncus felis at fermentum.
    Donec lorem magna, ultricies a
    nunc sit amet, blandit
    fringilla nunc. In vestibulum
    velit ac felis rhoncus
    pellentesque. Mauris at tellus
    enim. Aliquam eleifend tempus
    dapibus. Pellentesque commodo,
    nisi sit amet hendrerit
    fringilla, ante odio porta
    lacus, ut elementum justo
    nulla et dolor.'''
    
    from itertools import cycle
    
    for line in data.splitlines():
        words = line.split()
        _l = [[' '] for i in range(len(words)-1)]
        spaces = cycle(_l)
        for s, i in zip(spaces, range(30-len(line))):
            s[-1] += ' '
        for w, _l in zip(words, _l):
            print(''.join([w, *_l]), end='')
        print(words[-1])
    

    Prints:

    Lorem  ipsum  dolor  sit amet,
    consectetur  adipiscing  elit.
    Vestibulum    sagittis   dolor
    mauris,  at  elementum  ligula
    tempor  eget.  In quis rhoncus
    nunc,  at  aliquet orci. Fusce
    at   dolor   sit   amet  felis
    suscipit   tristique.   Nam  a
    imperdiet   tellus.  Nulla  eu
    vestibulum    urna.    Vivamus
    tincidunt  suscipit  enim, nec
    ultrices   nisi  volutpat  ac.
    Maecenas   sit   amet  lacinia
    arcu,  non dictum justo. Donec
    sed  quam  vel  risus faucibus
    euismod.  Suspendisse  rhoncus
    rhoncus  felis  at  fermentum.
    Donec lorem magna, ultricies a
    nunc    sit    amet,   blandit
    fringilla  nunc. In vestibulum
    velit    ac    felis   rhoncus
    pellentesque. Mauris at tellus
    enim.  Aliquam eleifend tempus
    dapibus. Pellentesque commodo,
    nisi    sit   amet   hendrerit
    fringilla,   ante  odio  porta
    lacus,   ut   elementum  justo
    nulla         et        dolor.
    

    EDIT: If last line doesn't have to be justified, use this:

    from itertools import cycle
    
    lines = data.splitlines()
    
    for line in lines[:-1]:
        words = line.split()
        _l = [[' '] for i in range(len(words)-1)]
        spaces = cycle(_l)
        for s, i in zip(spaces, range(30-len(line))):
            s[-1] += ' '
        for w, _l in zip(words, _l):
            print(''.join([w, *_l]), end='')
        print(words[-1])
    
    print(lines[-1])
    

    Prints:

    Lorem  ipsum  dolor  sit amet,
    consectetur  adipiscing  elit.
    Vestibulum    sagittis   dolor
    mauris,  at  elementum  ligula
    tempor  eget.  In quis rhoncus
    nunc,  at  aliquet orci. Fusce
    at   dolor   sit   amet  felis
    suscipit   tristique.   Nam  a
    imperdiet   tellus.  Nulla  eu
    vestibulum    urna.    Vivamus
    tincidunt  suscipit  enim, nec
    ultrices   nisi  volutpat  ac.
    Maecenas   sit   amet  lacinia
    arcu,  non dictum justo. Donec
    sed  quam  vel  risus faucibus
    euismod.  Suspendisse  rhoncus
    rhoncus  felis  at  fermentum.
    Donec lorem magna, ultricies a
    nunc    sit    amet,   blandit
    fringilla  nunc. In vestibulum
    velit    ac    felis   rhoncus
    pellentesque. Mauris at tellus
    enim.  Aliquam eleifend tempus
    dapibus. Pellentesque commodo,
    nisi    sit   amet   hendrerit
    fringilla,   ante  odio  porta
    lacus,   ut   elementum  justo
    nulla et dolor.