Output in two columns

Asked

Viewed 1,259 times

1

The output of my code makes a list in a column.

Code:

path = '/home/allan/Área de trabalho/adjetivos.txt'
i = 0
lista = []
conta = 1
with open (path) as file_obj:
    ler = file_obj.readlines()
for le in ler:

    #print(le.rstrip())
    lista.append(le)

for i in lista:
    tam = len(lista)
    #print(tam)
    if i == lista[0]:
        print("1 ano: Bodas de "+str(i.title().rstrip()))
    elif i != lista[0]:
        conta = 1 + conta
        print(str(conta)+" anos: Bodas de "+i.title().rstrip())

Current output:

1 ano: Bodas de Ágata
2 anos: Bodas de Água-Marinha
3 anos: Bodas de Âmbar
4 anos: Bodas de Alabastro
5 anos: Bodas de Alexandrita
6 anos: Bodas de Amazônia
7 anos: Bodas de Ametista
8 anos: Bodas de Andaluzite
9 anos: Bodas de Aventurina
10 anos: Bodas de Axinite
...

...Thus continues

I would like to "break the text", that the list continues beside as in the image:

inserir a descrição da imagem aqui

How can I do?


for texto in textos:
    print(max(len(texto)))

Why can’t I have the same effect of counting the characters as you did using listcomp? My interpretation of the code working on pythontutor is that 2 items on the list form 1, Ex: "coffee","sugar" -> "sugar coffee". It seems magical, how he manages to include himself?
Here:
Is this how it happens? See below: escritas[pos % linhas_coluna] would be like that:

...
[3 % 25]
[4 % 25]
[5 % 25]
...

So I’d take the 3 and would assign to anos: Bodas de Âmbar (espaço de 25)

texto.ljust(tamanho, ' ') would be:

anos: Bodas de Âmbar (espaço de 25) ,right?
I can’t see this text going right, just to ljust(left) thus forming a single column!
Remembering: The program is working perfectly well, but I can’t reach the logic itself. How can he split in two if everything goes left??

1 answer

2


I would start by simplifying and making the code more Pythonic before even starting to break into columns.

For this you can use list comprehensions for the construction of the list of adjectives, as well as enumerate not have to build the positions manually:

path = '/home/allan/Área de trabalho/adjetivos.txt'
with open (path) as file_obj:
    ler = file_obj.readlines()

lista = [le.strip() for le in ler] #strip apenas na passagem para a lista
for pos,adjetivo in enumerate(lista):
    print("{} ano{}: Bodas de {}".format(pos+1, "" if pos == 0 else "s", adjetivo.title()))

To break into columns you can create a new list with the texts that would be written instead of just the adjectives that came from the file. Then create another list that corresponds to the rows of the columns, and pass each text to the corresponding row.

To organize and structure can create a function that does this:

from math import ceil

def escrita_colunas(textos, colunas):
    linhas_coluna = ceil(len(textos) / colunas)
    tamanho = max([len(texto) for texto in textos]) + 1 #+1 para criar espaço entre colunas
    escritas = [''] * linhas_coluna

    for pos, texto in enumerate(textos):
        escritas[pos % linhas_coluna] += texto.ljust(tamanho, ' ')

    for escrita in escritas:
        print(escrita)

I used the ljust to align each text to the left based on the larger tamanho of the various texts to be written, which will allow creating visual alignment.

To put the text in the right line I used the module operator %. To better understand how this operator works we can start by considering the following code:

for i in range(15):
    print(i % 5)

Which produces the following result:

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

See for yourself at Ideone

Here we see as we do % 5 the number will always be between 0 and 4 and in a circular way. Applying to your example of 50 texts and 2 columns will give pos % 25 which will give you a number always between 0 and 24. It will be 0 to 24 for the first column and then again 0 to 24 for the second column.

That said, just build the texts to be written and call the function:

path = '/home/allan/Área de trabalho/adjetivos.txt'
with open (path) as file_obj:
    ler = file_obj.readlines()

lista = [le.strip() for le in ler]
textos = []
for pos,adjetivo in enumerate(lista):
    textos.append("{} ano{}: Bodas de {}".format(pos+1,"" if pos == 0 else "s",adjetivo.title()))

escrita_colunas(textos, 2)

See the column writing function working on Ideone

Edit:

Considering that the function I did of writing in columns was not clear to you I decided to redo it being as manual as possible not using any native function, to see the whole process:

def escrita_colunas(textos, colunas):
    linhas_coluna = ceil(len(textos) / colunas)

    tamanho_max = 0 
    for texto in textos: #achar o tamanho do maior texto entre todos os textos
        tamanho = len(texto) + 1 #+1 para dar espaço entre colunas
        if tamanho > tamanho_max:
            tamanho_max = tamanho

    escritas = [''] * linhas_coluna #criar as colunas

    linha = 0 
    for texto in textos:
        #se chegou ao limite de linhas desta coluna volta a 0 para
        #"passar para a próxima coluna"
        if linha == linhas_coluna:
            linha = 0

        #quantos carateres faltam para chegar a quantidade de carateres da coluna
        carateres_faltam = tamanho_max - len(texto) 

        #colocar os carateres que faltam como espaços a seguir ao texto
        texto_inserir = texto + (' ' * carateres_faltam)

        escritas[linha] = escritas[linha] + texto_inserir
        linha = linha + 1

    for escrita in escritas:
        print(escrita)

See also this version on Ideone working

  • I pointed out 3 doubts. I accepted but did not understand why the string 'size' returns 43. tamanho = max([len(texto) for texto in textos]) + 1 Here where I don’t understand anymore: for pos, texto in enumerate(textos):&#xA; escritas[pos % linhas_coluna] += texto.ljust(tamanho, ' ') My interpretation: ’s writing[From 0 to 49 % 25 ] <-- I don’t get it, 50 % 25 = 0 =+ <-- Add where? text.ljust(43, ' ') #text with 43 left-justified spaces , an empty space ' '. <-- Besides the size being 43 I didn’t understand the empty.

  • @Allanbelem size returns 43 because it considers the texts already constructed as "1 year: Marriage of Agata" rather than just the adjectives. In += texto.ljust(tamanho, ' ') we are adding the current text aligned to the left with size 43, and if you have less add spaces to the right until you 43. In escritas[pos % linhas_coluna] happens that to 50 elements and 2 columns will give pos % 25 which will be a number between 0 and 24 always. It is a way to ensure that it does not exceed 24 and always returns to 0 being circular. If you see the editing history see another way to do the same

  • @Allan If you want to be even more aware of how the module operator works in this case, observe the code and the output of this programme. Another thing that would be interesting is to visualize the code in my answer on python online viewer which is quite intuitive and gives you a very visual sense of what is happening

  • I am studying your code, I still find myself confused, I would like to know something else about the format of your code, the way it is described summarizes the functions in a single line, there is a technical name for this representation? I want to learn this way, since the advanced/intermediate books teach the way you presented them.

  • @Allanbelem If you’re referring to something like lista = [le.strip() for le in ler] then yes, it’s called List Comprehensions. So I advise you to read this documentation article to get more familiar with how it works. The main idea however to make code shorter, simpler and readable

  • @Allanbelem I re-edited my answer by placing a writing function in fully manual columns, to be as simple as possible without using native functions. See if you can understand the code and if it makes sense, preferably by looking at pythontutor as well. If you have questions do not hesitate to ask.

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.