Home > Software design >  How to print the data with equal spacing?
How to print the data with equal spacing?

Time:10-29

Data:

game_match = {'G02': ['MineCraft', 'S', '5', 5, 3, 2, 0, 0], 'G05': ['Hopscotch', 'N', '2', 5, 3, 2, 0, 0], 'G07': ['Dominoes', 'S', '5', 5, 2, 3, 0, 2], 'G08': ['Chess', 'N', '3', 5, 2, 3, 1, 2], 'G10': ['Monopoly', 'N', '3', 5, 1, 4, 2, 2]}

For each key and values in the dictionary I want to print:

  • key, values[0], values[1], values[2], values[3], values[4]

My code:

dash = '-' * 48
print(f'GameID{" ":7}Name{" ":7}Weight{" ":2}Nplayer{" ":2}Win{" ":2}', end='')
print('')
print(dash)
for k, v in game_match.items():
    print(f'{k:10}{v[0]:^5}({v[1]}){" ":^5}{v[2]:6}{v[3]:3}{" ":6}{v[4]}')

Output:

GameID       Name       Weight  Nplayer  Win  
------------------------------------------------
G02       MineCraft(S)     5       5      3
G05       Hopscotch(N)     2       5      3
G07       Dominoes(S)     5       5      2
G08       Chess(N)     3       5      2
G10       Monopoly(N)     3       5      1

I want to print the data above with equal spacing, but seem to fail. What code or format is the right one for this?

Expected Output:

GameID       Name       Weight  Nplayer  Win  
------------------------------------------------
G02       MineCraft(S)     5       5      3
G05       Hopscotch(N)     2       5      3
G07       Dominoes(S)      5       5      2
G08       Chess(N)         3       5      2
G10       Monopoly(N)      3       5      1

CodePudding user response:

Your error is that the field size should not be less than the maximum size of a field. You use 5 for the second field, when the max is 9. If I just change that value with:

...
    print(f'{k:10}{v[0]:>9}({v[1]}){" ":^5}{v[2]:6}{v[3]:3}{" ":6}{v[4]}')

it gives:

GameID       Name       Weight  Nplayer  Win  
------------------------------------------------
G02       MineCraft(S)     5       5      3
G05       Hopscotch(N)     2       5      3
G07        Dominoes(S)     5       5      2
G08           Chess(N)     3       5      2
G10        Monopoly(N)     3       5      1

I have choosed to align it right to make easier to concatenate it with the third field. In order to align it left, the concatenation should occur first:

...
    print(f'{k:10}{v[0]   "("   v[1]   ")":12}{" ":^5}{v[2]:6}{v[3]:3}{" ":6}{v[4]}')

to get:

GameID       Name       Weight  Nplayer  Win  
------------------------------------------------
G02       MineCraft(S)     5       5      3
G05       Hopscotch(N)     2       5      3
G07       Dominoes(S)      5       5      2
G08       Chess(N)         3       5      2
G10       Monopoly(N)      3       5      1

CodePudding user response:

Take look at str methods

  • ljust
  • center
  • rjust

They need at least one argument which is width, they produce string of given width by adding spaces (this could be changed using 2nd optional argument) or return original (if it is already longer). Consider following example

for x in ["A","BB","CCC","DDDD","EEEEE"]:
    print(x.rjust(5))

output

    A
   BB
  CCC
 DDDD
EEEEE

ljust does just to left, rjust does just to right, center does center

CodePudding user response:

Parse the "Name" column before the print statement so you can format that column correctly, something like this:

...

for k, v in game_match.items():
    name = f"{v[0]}({v[1]})"
    print(f'{k:10}{name:<12}{" ":^5}{v[2]:6}{v[3]:3}{" ":6}{v[4]}')

CodePudding user response:

Try using {" "*<int>} instead of {" ":<int>}.

    dash = '-' * 48
    print(f'GameID{" ":7}Name{" ":7}Weight{" ":2}Nplayer{" ":2}Win{" ":2}', end='')
    print('')
    print(dash)
    for k, v in game_match.items():
        print(f'{k:10}{v[0]:^5}({v[1]}){" "*(11-len(v[0]) 3)}{v[2]:6}{v[3]:3}{" ":6}{v[4]}')

Output :

    GameID       Name       Weight  Nplayer  Win
    ------------------------------------------------
    G02       MineCraft(S)     5       5      3
    G05       Hopscotch(N)     2       5      3
    G07       Dominoes(S)      5       5      2
    G08       Chess(N)         3       5      2
    G10       Monopoly(N)      3       5      1

CodePudding user response:

The problem is that your "game name" is longer than 5 spaces you reserved. It is 12 chars length to be more exactly.

With a little change in you print code, I suppose I cold solve this. Check if it is enough to you.

dash = '-' * 48
print(f'GameID{" ":7}Name{" ":7}Weight{" ":2}Nplayer{" ":2}Win{" ":2}', end='')
print('')
print(dash)
for k, v in game_match.items():
    game_name = f"{v[0]}({v[1]})"
    print(f'{k:10}{game_name:12}{" ":^5}{v[2]:6}{v[3]:3}{" ":6}{v[4]}')

The output was that.

GameID       Name       Weight  Nplayer  Win  
------------------------------------------------
G02       MineCraft(S)     5       5      3
G05       Hopscotch(N)     2       5      3
G07       Dominoes(S)      5       5      2
G08       Chess(N)         3       5      2
G10       Monopoly(N)      3       5      1

CodePudding user response:

Let's break this problem down into smaller pieces and think about it.

You clearly already know how to combine two fields together with the text you need:

>>> a = "Minecraft"  # v[0]
>>> b = "S"  # v[1]
>>> f'{a}({b})'  # v[0] and v[1] combined, with other text
'Minecraft(S)'

It looks like you already know how to format a string into a column of a fixed width; I'll use a width of 15 below:

ab_combined = "Minecraft(S)"
>>> f"{ab_combined:15}"  # v[0] and v[1] formatted into a column with other text
'Minecraft(S)   '

The problem you are running into is how to combine two fields together into a single column of a certain width at the same time.

In other words, you want to combine the field a and field b (which correspond to v[0] and v[1]) into a string AND THEN format the string into a column. So let's build up to that in a couple steps:

f'{v[0]}({v[1]})'

Great, we have our combined text. But how do you take that combined string of text and put it into a column of some width? There's a couple ways. Here's one:

field_v0_and_v1 = f'{v[0]}({v[1]})'
f'{field_v0_and_v1:15}'

That's fine! Two lines is FINE. But you can also do it in one line this way, using nested f-strings. It's harder to read. I don't really recommend it at your current skill level. But it's also not TOO bad:

f"{f'{v[0]}({v[1]})':15}"

You can drop that in with the rest of your formatting string using string concatenation:

f'{k:10}'  f"{f'{v[0]}({v[1]})':15}" f'{v[2]:>6}{v[3]:>6}{v[4]:>6}'

Breaking up your f-strings into pieces using concatenation like this really helps you think through what you are doing, one piece at a time. I highly recommend it.

Note that I have changed the numerical fields to be right-aligned with the > character, which is what you wanted. I have also deleted the extraneous space-only columns (e.g. f'{" ":6}'), which aren't necessary.

<A further word about concatenation, because it's useful>

Notice the spaces between the f-string-literals above. This combines the strings using concatenation, and works with any strings:

>>> 'a' 'b'
'ab'

But you can't do it using variables that happen to contain strings; the python parser doesn't know what's in your variables:

>>> a, b = 'a', 'b'
>>> a b
# SyntaxError

...when you are not using string-literals you have to use the addition operator, or use formatting:

>>> a   b
'ab'
>>> f'{a}{b}'
'ab'

FINAL TIP: if you want dynamically adjust your numerical column widths, you can store the value in a variable and evaluate them in the f-string:

col_w = 6
f'{k:10}'  f"{f'{v[0]}({v[1]})':15}" f'{v[2]:>{col_w}}{v[3]:>{col_w}}{v[4]:>{col_w}}'
  • Related