I have created a python program that prints a vertical bar graph made from fields and values inputted by the user. It works by first creating a horizontal bar graph and then going through each layer and determining whether to print a letter, a "|"
, a "_"
, or a space. I would appreciate any feedback on the program and things I could do to improve it.
import re
feilds = input("Input| ex: dogs,10 cats,23 birds,67\n").strip()
while not re.match("^(\w+,\d+ ?)+$", feilds):
feilds = input("invalid input, use this format:\nfeild,value feild,value feild,value...\n").strip()
width = int(input("How wide is your output window in characters? "))
scale = float(input("Scale: "))
vals = dict([feild.split(",") for feild in feilds.split(" ")])
for k, v in vals.items():
vals[k] = int(v)
spacing = int(width / len(vals.keys()))
horizontal = ["-" * int(v * scale) + "|" + k[::-1] for k, v in vals.items()]
vertical = []
for x in reversed(range(len(max(horizontal, key=len)))):
layer = []
for val in horizontal:
try:
if val[x] == "-":
layer.append("|")
elif val[x] == "|":
layer.append("_")
else:
layer.append(val[x])
except IndexError:
layer.append(" ")
vertical.append(layer)
print("\n")
print("\n".join((" " * (spacing - 1)).join(layer) for layer in vertical))
ex:
input:
dogs,20 cats,18 fish,25 birds,10
80
.5
output:
f
i
d s
o c h
g a _
s t |
_ s | b
| _ | i
| | | r
| | | d
| | | s
| | | _
| | | |
| | | |
| | | |
| | | |
| | | |
NOTE: output might be messed up if the width is off by a lot. Make sure to input a width close to what it is.
1 Answer 1
feilds
is spelled fields
. IDEs like PyCharm will identify spelling mistakes in variables.
Why is there a ?
after the space in your regex? Currently I believe it will pass input looking like
key,1key,2key,3
So you have to fix that edge case, probably by adding a final key-value pair with no space, and making the space in the first group mandatory.
This:
vals = dict([feild.split(",") for feild in feilds.split(" ")])
for k, v in vals.items():
vals[k] = int(v)
should be
vals = {k: int(v)
for field in fields.split(' ')
for k, v in field.split(',')}
i.e. don't construct a list in memory only to throw it away.
This:
spacing = int(width / len(vals.keys()))
can be
spacing = width // len(vals)
This:
for x in reversed(range(len(max(horizontal, key=len)))):
doesn't actually need an index at all, since you don't use it. Also, lumping everything into one line is confusing. Instead:
longest_horz = max(len(h) for h in horz)
for v in val[longest_horz-1::-1]:
Then use v
instead of val[x]
.