String output formatting - python

My Code:
infile = open("table1.txt", "r")
a_list = infile.read().split("\n")
infile.close()
for pass_num in range(len(a_list)-1, 0, -1):
for i in range(0, pass_num):
if int(a_list[i].split(",")[1].strip()) > int(a_list[i+1].split(",")[1].strip()):
a_list[i], a_list[i+1] = a_list[i+1], a_list[i]
if (int(a_list[i].split(",")[1].strip()) == int(a_list[i+1].split(",")[1].strip())) and ((int(a_list[i].split(",")[2]) - int(a_list[i].split(",")[3].strip())) > (int(a_list[i+1].split(",")[2].strip()) - int(a_list[i+1].split(",")[3].strip()))):
a_list[i], a_list[i+1] = a_list[i+1], a_list[i]
if (int(a_list[i].split(",")[1].strip()) == int(a_list[i+1].split(",")[1].strip())) and ((int(a_list[i].split(",")[2]) - int(a_list[i].split(",")[3].strip())) == (int(a_list[i+1].split(",")[2].strip()) - int(a_list[i+1].split(",")[3].strip()))):
if (int(a_list[i].split(",")[2])) > int(a_list[i+1].split(",")[2]):
a_list[i], a_list[i+1] = a_list[i+1], a_list[i]
a_list.reverse()
print(" Team" + " "*(30-len(" Team")) + "Points" + " "*2 + "Diff" + " "*4 + "Goals")
for i in range(len(a_list)):
team = a_list[i].split(",")[0]
points = a_list[i].split(",")[1]
goalfor = int(a_list[i].split(",")[2].strip())
goalagainst = int(a_list[i].split(",")[3].strip())
diff = goalfor - goalagainst
print(str(i+1).rjust(2) + ". " + '{0:27} {1:4} {2:4} {3:5} : {4:2}'.format(team, points, diff, goalfor, goalagainst))
#Area of interest above^
Current output:
Desired output:
Would anyone know how to edit the area of interest in the commented piece of code to produce the desired output with the 9's lined up underneath the 3 in 13? Ive been trying .rjust(1) but it wont seem to work.

Python string format support align.
align ::= "<" | ">" | "=" | "^"
'<' Forces the field to be left-aligned within the available space (this is the default for most objects).
'>' Forces the field to be right-aligned within the available space (this is the default for numbers).
'=' Forces the padding to be placed after the sign (if any) but before the digits. This is used for printing fields in the form ‘+000000120’. This alignment option is only valid for numeric types.
'^' Forces the field to be centered within the available space.
So use {:>} for right align.
DEMO
>>> print "{}\t{:<2}".format(1, 20)
1 20
>>> print "{}\t{:<2}".format(1, 2)
1 2
>>> print "{}\t{:>2}".format(1, 2)
1 2
>>> print "{}\t{:>2}".format(1, 20)
1 20
In your case, just align the format in the following way:
print(str(1).rjust(2) + ". " + '{0:27} {1:>4} {2:4} {3:5} : {4:2}'.format("adasd", 1, -12, 1, 2))
^^^

Related

Parse nested expression to retrieve each inner functions

Suppose I have an expression as shown below:
expression = "LEN(Replace(Lower(UPPER([ProductName]+[ProductName])), 'chaichai', 'chai'))"
Required output:
['UPPER([ProductName]+[ProductName])','Lower(UPPER([ProductName]+[ProductName]))','Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai')','LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))']
I have tried the below code but not getting required result:
exp_splits = expression.strip(')').split('(')
for i_enm, i in enumerate(range(len(exp_splits)-2, -1, -1), start=1):
result.append(f"{'('.join(exp_splits[i:])}{')'*i_enm}")
print(result)
my code's output:
["UPPER([ProductName]+[ProductName])),'chaichai','chai')", "Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))", "Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai')))", "LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))))"]
import re
e = "LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))"
print ([e[i:j+1] for i in range(len(e)) for j in range(len(e)) if e[i:j+1].count('(') == e[i:j+1].count(')') != 0 and (e[i-1] == '(' or i == 0) and e[j] == ')'])
Output:
["LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))", "Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai')", 'Lower(UPPER([ProductName]+[ProductName]))', 'UPPER([ProductName]+[ProductName])']
Unfolded version:
for i in range(len(e)):
for j in range(len(e)):
#Check for same number of opening/closing parenthesis
if e[i:j+1].count('(') == e[i:j+1].count(')') != 0:
#Check that (first char is preceded by an opening parenthesis OR that first char is the beginning of e) AND last char is a parenthesis
if (e[i-1] == '(' or i == 0) and e[j] == ')':
print (e[i:j+1])
Output:
LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))
Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai')
Lower(UPPER([ProductName]+[ProductName]))
UPPER([ProductName]+[ProductName])
Approach using split and for loop
Here's another approach to get this done. In this approach, I am splitting the string into parts.
Splitting them by left parenthesis and right parenthesis.
Then concatenating them each time to create the expression
Assumption: The expression has equal number of left and right parenthesis
Step 1: Count the number of left parenthesis in the string
Step 2: Split the expression by left parenthesis
Step 3: pop the last expression from the list of left parenthesis and
store into right expression. This contains right parenthesis
Step 4: Split the expression by right parenthesis
Step 5: Now that you have both the sides, stitch them together
Note: While concatenating the expression, left side goes from right
to left (index -1 thru 0) and right side goes from left to right
(index 0 to -1)
Note: For each iteration, you need to concatenate the previous answer
with left and right
Code is as shown below:
expression = "LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))"
n = expression.count('(')
exp_left = expression.split('(')
exp_right = exp_left.pop().split(')')
exp_list = []
exp_string = ''
for i in range(n):
exp_string = exp_left[-i-1] + '(' + exp_string + exp_right[i] + ')'
exp_list.append(exp_string)
for exp in exp_list: print (exp)
The output of this will be:
UPPER([ProductName]+[ProductName])
Lower(UPPER([ProductName]+[ProductName]))
Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai')
LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))
Below code is the same as above. I have added comments to each line for you to understand what's being done.
expression = "LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))"
#find the number of equations in the string. Count of '(' will give you the number
n = expression.count('(')
#split the string by left parenthesis. You get all the functions + middle part + right hand side
exp_left = expression.split('(')
#middle + right hand part is at position index -1. Use pop to remove the last value
#Use the popped string to split by right parenthesis
#result will be middle part + all right hand side parts.
#empty string if there was no text between two right parenthesis
exp_right = exp_left.pop().split(')')
#define a list to store all the expressions
exp_list = []
#Now put it all together looping thru n times
#store the expression in a string so you can concat left and right to it each time
exp_string = ''
for i in range(n):
#for each iteration, concat left side + ( + middle string + right side + )
#left hand side: concat from right to left (-1 to 0)
#right hand side: concat from left to right (0 to n-1)
exp_string = exp_left[-i-1] + '(' + exp_string + exp_right[i] + ')'
#append the expression to the expression list
exp_list.append(exp_string)
#print each string separately
for exp in exp_list: print (exp)
Approach using While Statement
Here's how to do the search and extract version.
e = "LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))"
x = e.count('(')
for i in range(x-1): e = e[e.find('(')+1:]
expression = e[:e.find(')')+1]
print (expression)
The result of this will be:
UPPER([ProductName]+[ProductName])
If you want all of them, then you can do this until you reach the innermost brackets.
e = "LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))"
#x = e.count('(')
#for i in range(x-1): e = e[e.find('(')+1:]
#expression = e[:e.find(')')+1]
exp_list = [e]
while e.count('(') > 1:
e = e[e.find('(')+1:e.rfind(')')]
while e[-1] != ')': e = e[:e.rfind(')')+1]
exp_list.append(e)
for exp in exp_list:
print (exp)
The output of this will be:
LEN(Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai'))
Replace(Lower(UPPER([ProductName]+[ProductName])),'chaichai','chai')
Lower(UPPER([ProductName]+[ProductName]))
UPPER([ProductName]+[ProductName])

Replace all occurrences of the substring in string using string slicing

I want to replace all substring occurrences in a string, but I wish not to use the replace method. At the moment, experiments have led me to this:
def count_substrings_and_replace(string, substring, rpl=None):
string_size = len(string)
substring_size = len(substring)
count = 0
_o = string
for i in range(0, string_size - substring_size + 1):
if string[i:i + substring_size] == substring:
if rpl:
print(_o[:i] + rpl + _o[i + substring_size:])
count += 1
return count, _o
count_substrings_and_replace("aaabaaa", "aaa", "ddd")
but I have output like this:
dddbaaa
aaabddd
not dddbddd.
Update 1:
I figured out that I can only replace correctly with a string of the same length of substring. For example for count_substrings_and_replace("aaabaaa", "aaa", "d") I got output: (2, 'dbaad') not dbd
Update 2:
Issue described in update 1 did appear because of string comparing relative to the original string (line 8) that does not change throughout the process.
Fixed:
def count_substrings_and_replace(string, substring, rpl=None):
string_size = len(string)
substring_size = len(substring)
count = 0
_o = string
for i in range(0, string_size - substring_size + 1):
if _o[i:i + substring_size] == substring:
if rpl:
_o = _o[:i] + rpl + _o[i + substring_size:]
count += 1
return count, _o
count_substrings_and_replace("aaabaaa", "aaa", "d")
Output: (2, dbd)
You never update the value of _o when a match is found, you're only printing out what it'd look like if it was to be replaced. Instead, inside that innermost if statement should be two lines like:
_o = _o[:i] + rpl + _o[i + substring_size:]
print(_o)
That would print the string every time a match is found and replaced, moving the print statement to run after the for loop would make it only run once the entire string was parsed and replaced appropriately.
Just my mistake. I had to pass the value to the variable on each iteration not print:
_o = _o[:i] + rpl + _o[i + substring_size:]

Returning original string with symbols between each character

I'm trying to make my program return the exact same string but with ** between each character. Here's my code.
def separate(st):
total = " "
n = len(st + st[-1])
for i in range(n):
total = str(total) + str(i) + str("**")
return total
x = separate("12abc3")
print(x)
This should return:
1**2**a**b**c**3**
However, I'm getting 0**1**2**3**4**5**6**.
You can join the characters in the string together with "**" as the separator (this works because strings are basically lists in Python). To get the additional "**" at the end, just concatenate.
Here's an example:
def separate(st):
return "**".join(st) + "**"
Sample:
x = separate("12abc3")
print(x) # "1**2**a**b**c**3**"
A note on your posted code:
The reason you get the output you do is because you loop using for i in range(n): so the iteration variable i will be each index in st. Then when you call str(total) + str(i) + str("**"), you cast i to a string, and i was just each index (from 0 to n-1) in st.
To fix that you could iterate over the characters in st directly, like this:
for c in st:
or use the index i to get the character at each position in st, like this:
for i in range(len(st)):
total = total + st[i] + "**"
welcome to StackOverflow!
I will explain part of your code line by line.
for i in range(n) since you are only providing 1 parameter (which is for the stopping point), this will loop starting from n = 0, 1, 2, ... , n-1
total = str(total) + str(i) + str("**") this add i (which is the current number of iteration - 1) and ** to the current total string. Hence, which it is adding those numbers sequentially to the result.
What you should do instead is total = str(total) + st[i] + str("**") so that it will add each character of st one by one
In addition, you could initialize n as n = len(st)

python Directory structure display of comma delimited string based on open and closed parentheses

I am learning python. This is my first stackoverflow question too and struggling with formatting the output to show my requirement.
I am writing python code for converting a string with comma delimited values into a level hierarchy display data like the following.
s = "(id,cb,e(id,fn,eT(id), ln),lc)"
I want a output like this
-id
-cb
-e
--id
--fn
--eT
---id
--ln
-lc
so far I have done some coding, but I am struggling to refine it.
class parent-child():
stack = []
def tree_recur(self,employee, level):
s = s[s.index("(")+1:s.rindex(")")]
ind = 0
while(s.rstrip != null or s != ""):
ss = s.index(",")
words = s[ind:ss]
parenind = words.index("(")
if parenind == -1:
stack.append(level,words)
s = s[ss+1:len(s)]
else:
stack.append(s[ss+1:parenind-1])
closeparenind = s.index(")")
ss1= s[parenind:closeparenind]
return tree_recur(self,ss1,level+1)
def main():
s = "(id,created,employee(id,firstname,employeeType(id), lastname),location)"
level = 0
print(E = parent-child(s, level))
main()
can someone help me with refining this code. I don't know how to print "-" before string depending on how deep the level. That is level 1 one hyphen, level 2 two hyphens, level 3 three hyphens and move up a level when is parentheses is closed. I would like to thank for your help and time spent on helping me.
Since you're already trying to parse. The simpler way would be to iterate through each character.
s = "(id,cb,e(id,fn,eT(id), ln),lc)"
hyphens = 0
result = []
current = ""
for c in s:
if c == "(": hyphens += 1
if c == ")": hyphens -= 1
if c.isalnum():
if not current:
current += "-" * hyphens
current += c
elif current:
result.append(current)
current = ""
result = " ".join(result)
print(result)
Which prints:
-id -cb -e --id --fn --eT ---id --ln -lc
Edit:
I can understand you want it in this format:
-id
-cb
-e
--id
--fn
--eT
---id
--ln
-lc
This can be done so by changing:
current += " " * 2 * (hyphens - 1) + "-" * hyphens
and
result = "\n".join(result)

Formatting loop for strings

I'm having trouble formatting the strings below. Trying to keep the message centered with the borders, but having a hard time executing it. Below is what output I want and below that is my code I have so far. Note: I need to have a space on the left and right columns of the longest line and I need to utilize the split() func.
+---------------+
| STOP! |
| DANGER AHEAD |
| Drive Safely! |
+---------------+
def border_sign(note):
letter_count = 0
for i in note:
letter_count += 1
return "+-------+\n| {} |\n+-------+\n".format(note)
border_sign("STOP\nDANGER AHEAD\nDrive safely!")
Split the string into separate lines, then center each line. Remember to either print each line immediately within the function, build up a list, or yield each line rather than returning after the first line. You can also determine and use a calculated width rather than a static value.
def border_sign(note):
note = note.splitlines()
m = len(max(note, key=len))
yield ('-'*m).join('++')
for line in note:
yield ("|{:^%d}|" % m).format(line)
yield ('-'*m).join('++')
print(*border_sign("STOP\nDANGER AHEAD\nDrive safely!"), sep='\n')
Quick sample to consider, not production ready code:
def border_sign(note):
rows = note.splitlines()
mlen = len(max(rows, key=len))
print "+" + "-" * (2+mlen) + "+"
for row in rows:
print ("| {:^"+str(mlen)+"} |").format(row)
print "+" + "-" * (2+mlen) + "+"
def border_sign(x):
splitted = x.splitlines()
M = max(map(len,splitted))
horiz = '+-%s-+' % (M*'-')
patiz = '| {0: ^%d} |' % M
print(horiz,*map(patiz.format,splitted), horiz, sep='\n')
border_sign("STOP\nDANGER AHEAD\nDrive safely!")
patiz.format is a function, then can be used in map

Categories