Drawing a table for data from file
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
8
down vote
favorite
I wrote a function for drawing a table for data that comes from file:
import data_manager
import os
table = data_manager.get_table_from_file('games.csv')
len_of_longest_name = 0
i = 0
while i < len(table):
if len_of_longest_name < len(table[i][1]):
len_of_longest_name = len(table[i][1])
i += 1
i = 0
len_of_longest_studio = 0
while i < len(table):
if len_of_longest_studio < len(table[i][2]):
len_of_longest_studio = len(table[i][2])
i += 1
print("/", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "\")
# constructing string
i = 0
while i < len(table):
string = '|'
string += table[i][0] + '|'
if len(table[i][1]) < len_of_longest_name:
spaces = (len_of_longest_name - len(table[i][1])) * ' '
string += table[i][1] + spaces + '|'
else:
string += table[i][1] + '|'
if len(table[i][2]) < len_of_longest_studio:
spaces = (len_of_longest_studio - len(table[i][2])) * ' '
string += table[i][2] + spaces + '|'
else:
string += table[i][2] + '|'
string += table[i][3] + '|'
if len(table[i][4]) < 2:
string += table[i][4] + ' |'
else:
string += table[i][4] + '|'
if i < len(table) - 1:
print(string)
print("|", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "|")
else:
print(string)
i += 1
print("\", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "/")
The code works as I want but I think there's a better (shorter) method to do the same. Could you show me the method?
The output looks like this:
python beginner python-3.x formatting ascii-art
add a comment |Â
up vote
8
down vote
favorite
I wrote a function for drawing a table for data that comes from file:
import data_manager
import os
table = data_manager.get_table_from_file('games.csv')
len_of_longest_name = 0
i = 0
while i < len(table):
if len_of_longest_name < len(table[i][1]):
len_of_longest_name = len(table[i][1])
i += 1
i = 0
len_of_longest_studio = 0
while i < len(table):
if len_of_longest_studio < len(table[i][2]):
len_of_longest_studio = len(table[i][2])
i += 1
print("/", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "\")
# constructing string
i = 0
while i < len(table):
string = '|'
string += table[i][0] + '|'
if len(table[i][1]) < len_of_longest_name:
spaces = (len_of_longest_name - len(table[i][1])) * ' '
string += table[i][1] + spaces + '|'
else:
string += table[i][1] + '|'
if len(table[i][2]) < len_of_longest_studio:
spaces = (len_of_longest_studio - len(table[i][2])) * ' '
string += table[i][2] + spaces + '|'
else:
string += table[i][2] + '|'
string += table[i][3] + '|'
if len(table[i][4]) < 2:
string += table[i][4] + ' |'
else:
string += table[i][4] + '|'
if i < len(table) - 1:
print(string)
print("|", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "|")
else:
print(string)
i += 1
print("\", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "/")
The code works as I want but I think there's a better (shorter) method to do the same. Could you show me the method?
The output looks like this:
python beginner python-3.x formatting ascii-art
what was the source data like?
â hjpotter92
Jan 16 at 18:44
kH34Ju#&;Age of Empires II: The Age of Kings;Ensemble Studios;32;32n Every record looks like this, ";" is a separator.
â Voyt
Jan 16 at 19:10
2
Have you considered using a package such as terminaltables?
â 200_success
Jan 16 at 20:09
what isdata_manager
?
â Stephen Rauch
Jan 17 at 4:17
data_manager is a module that reads from file and returns list of lines in one variable
â Voyt
Jan 17 at 7:56
add a comment |Â
up vote
8
down vote
favorite
up vote
8
down vote
favorite
I wrote a function for drawing a table for data that comes from file:
import data_manager
import os
table = data_manager.get_table_from_file('games.csv')
len_of_longest_name = 0
i = 0
while i < len(table):
if len_of_longest_name < len(table[i][1]):
len_of_longest_name = len(table[i][1])
i += 1
i = 0
len_of_longest_studio = 0
while i < len(table):
if len_of_longest_studio < len(table[i][2]):
len_of_longest_studio = len(table[i][2])
i += 1
print("/", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "\")
# constructing string
i = 0
while i < len(table):
string = '|'
string += table[i][0] + '|'
if len(table[i][1]) < len_of_longest_name:
spaces = (len_of_longest_name - len(table[i][1])) * ' '
string += table[i][1] + spaces + '|'
else:
string += table[i][1] + '|'
if len(table[i][2]) < len_of_longest_studio:
spaces = (len_of_longest_studio - len(table[i][2])) * ' '
string += table[i][2] + spaces + '|'
else:
string += table[i][2] + '|'
string += table[i][3] + '|'
if len(table[i][4]) < 2:
string += table[i][4] + ' |'
else:
string += table[i][4] + '|'
if i < len(table) - 1:
print(string)
print("|", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "|")
else:
print(string)
i += 1
print("\", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "/")
The code works as I want but I think there's a better (shorter) method to do the same. Could you show me the method?
The output looks like this:
python beginner python-3.x formatting ascii-art
I wrote a function for drawing a table for data that comes from file:
import data_manager
import os
table = data_manager.get_table_from_file('games.csv')
len_of_longest_name = 0
i = 0
while i < len(table):
if len_of_longest_name < len(table[i][1]):
len_of_longest_name = len(table[i][1])
i += 1
i = 0
len_of_longest_studio = 0
while i < len(table):
if len_of_longest_studio < len(table[i][2]):
len_of_longest_studio = len(table[i][2])
i += 1
print("/", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "\")
# constructing string
i = 0
while i < len(table):
string = '|'
string += table[i][0] + '|'
if len(table[i][1]) < len_of_longest_name:
spaces = (len_of_longest_name - len(table[i][1])) * ' '
string += table[i][1] + spaces + '|'
else:
string += table[i][1] + '|'
if len(table[i][2]) < len_of_longest_studio:
spaces = (len_of_longest_studio - len(table[i][2])) * ' '
string += table[i][2] + spaces + '|'
else:
string += table[i][2] + '|'
string += table[i][3] + '|'
if len(table[i][4]) < 2:
string += table[i][4] + ' |'
else:
string += table[i][4] + '|'
if i < len(table) - 1:
print(string)
print("|", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "|")
else:
print(string)
i += 1
print("\", 6 * "-", "|", (len_of_longest_name - 2) * "-", "|", (len_of_longest_studio - 2) * "-", "|", "---", "/")
The code works as I want but I think there's a better (shorter) method to do the same. Could you show me the method?
The output looks like this:
python beginner python-3.x formatting ascii-art
edited Jan 16 at 20:07
200_success
123k14143401
123k14143401
asked Jan 16 at 17:47
Voyt
392
392
what was the source data like?
â hjpotter92
Jan 16 at 18:44
kH34Ju#&;Age of Empires II: The Age of Kings;Ensemble Studios;32;32n Every record looks like this, ";" is a separator.
â Voyt
Jan 16 at 19:10
2
Have you considered using a package such as terminaltables?
â 200_success
Jan 16 at 20:09
what isdata_manager
?
â Stephen Rauch
Jan 17 at 4:17
data_manager is a module that reads from file and returns list of lines in one variable
â Voyt
Jan 17 at 7:56
add a comment |Â
what was the source data like?
â hjpotter92
Jan 16 at 18:44
kH34Ju#&;Age of Empires II: The Age of Kings;Ensemble Studios;32;32n Every record looks like this, ";" is a separator.
â Voyt
Jan 16 at 19:10
2
Have you considered using a package such as terminaltables?
â 200_success
Jan 16 at 20:09
what isdata_manager
?
â Stephen Rauch
Jan 17 at 4:17
data_manager is a module that reads from file and returns list of lines in one variable
â Voyt
Jan 17 at 7:56
what was the source data like?
â hjpotter92
Jan 16 at 18:44
what was the source data like?
â hjpotter92
Jan 16 at 18:44
kH34Ju#&;Age of Empires II: The Age of Kings;Ensemble Studios;32;32n Every record looks like this, ";" is a separator.
â Voyt
Jan 16 at 19:10
kH34Ju#&;Age of Empires II: The Age of Kings;Ensemble Studios;32;32n Every record looks like this, ";" is a separator.
â Voyt
Jan 16 at 19:10
2
2
Have you considered using a package such as terminaltables?
â 200_success
Jan 16 at 20:09
Have you considered using a package such as terminaltables?
â 200_success
Jan 16 at 20:09
what is
data_manager
?â Stephen Rauch
Jan 17 at 4:17
what is
data_manager
?â Stephen Rauch
Jan 17 at 4:17
data_manager is a module that reads from file and returns list of lines in one variable
â Voyt
Jan 17 at 7:56
data_manager is a module that reads from file and returns list of lines in one variable
â Voyt
Jan 17 at 7:56
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
3
down vote
Python has many great ways to iterate. In general if you find yourself looping on an integer, like in the following code, there is a good chance you are doing it wrong. It is generally better to iterate on the data structure itself.
Sample code:
I will use this loop as an example:
len_of_longest_name = 0
i = 0
while i < len(table):
if len_of_longest_name < len(table[i][1]):
len_of_longest_name = len(table[i][1])
i += 1
Don't iterate on the length of a data structure:
This is probably not what you want:
while i < len(table):
It would likely be better as something like:
for row in table:
Or, if for some reason you really need the index, then:
for i, row in enumerate(table):
Example with looping on length removed:
So removing i
, and looping on table
, we get:
len_of_longest_name = 0
for row in table:
if len_of_longest_name < len(row[1]):
len_of_longest_name = len(row[1])
Use builtin functions.
Python have a max()
function. Using max()
, the example becomes:
len_of_longest_name = 0
for row in table:
len_of_longest_name = max(len_of_longest_name, len(row[1]))
Comprehensions:
Since max()
can take a comprehension the example loop can be reduced to:
len_of_longest_name = max(len(row[1]) for row in table)
That is six lines of code reduced to one.
add a comment |Â
up vote
2
down vote
Starting from what @Stephen Rauch said in his answer, you can greatly simplify your code.
You should definitely take a look at
str.join
,enumerate
,zip
and why you should not do string addition when concatenating many (not short) strings.I would first compute all column lengths (not just the two you calculate, relying on the fact that the other lengths are the same across rows). For this you can use nested list comprehensions.
I would declare the repeatedly re-used strings which make the table frame only once, instead of building them every loop iteration.
Finally, I would put this into a function to make it re-usable and add a
if __name__ == "__main__":
guard to allow importing this function from another script without running the code.
def data_table(table)
column_lens = [max(len(row[i]) for row in table)
for i in range(len(table[0]))]
# constructing string
separator = " | ".join("-" * (column_len - 2) for column_len in column_lens)
header = "/ " + separator + " \"
row_separator = "| " + separator + " |"
footer = "\ " + separator + " /"
new_table = [header]
for i, row in enumerate(table):
new_row = "|".join(column + " " * (column_len - len(column))
for column, column_len in zip(row, column_lens))
new_table.append("|" + new_row + "|")
if i < len(table) - 1:
new_table.append(row_separator)
new_table.append(footer)
return "n".join(new_table)
if __name__ == "__main__":
table = data_manager.get_table_from_file('games.csv')
print(data_table(table))
This prints for example:
/ ------ | --------------------------------- | -------------- | |
|kH34Ju%&|Age of Empires II: The Age of Kings|Ensemble Studios|32|32|
| ------ | --------------------------------- | -------------- | | |
|kH34*&23|Age of Empires I |Ensemble Studios|32|32|
------ | --------------------------------- | -------------- | | /
Note that this is a slightly different format (it has no sub-cells, as you do in your last two columns). Also note that if a column contains only cells of width 1 or 0, then the header and the table will be misaligned (since the header and footer row is at least 2 characters wide for each column.
Compared to your code, this has the great advantage that it works for every table that is defined as a list of lists.
add a comment |Â
up vote
-1
down vote
Thanks for your answers. I wrote this:
import data_manager
def table_lines():
string = ""
for indices in range(0, len(max_len)):
value = max_len[indices]
string += "|" + (value * "-")
string += "|"
return string
def data_lines(table):
data_string = "|"
for row in table:
for indices in range(0, len(row)):
if len(row[indices]) < max_len[indices]:
data_string += row[indices] + ((max_len[indices] - len(row[indices] )) * " ") + "|"
else:
data_string += row[indices] + "|"
print(table_lines())
print(data_string)
data_string = "|"
def get_longest(table):
for row in table:
value_len =
for element in row:
value_len.append(len(element))
# for debug print(row)
values_len.append(value_len)
# for debug print(values_len)
for row in values_len:
for indices in range(0, len(row)):
try:
if row[indices] > max_len[indices]:
max_len[indices] = row[indices]
except IndexError:
max_len.append(row[indices])
The output looks like this:
Now I will work on fixing a corners of table.
Thanks once more!
1
You should not be (implicitly even) using globals like you do. Instead return the objects you create inside your functions and pass them as arguments to the functions that need them.
â Graipher
Jan 17 at 15:53
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
Python has many great ways to iterate. In general if you find yourself looping on an integer, like in the following code, there is a good chance you are doing it wrong. It is generally better to iterate on the data structure itself.
Sample code:
I will use this loop as an example:
len_of_longest_name = 0
i = 0
while i < len(table):
if len_of_longest_name < len(table[i][1]):
len_of_longest_name = len(table[i][1])
i += 1
Don't iterate on the length of a data structure:
This is probably not what you want:
while i < len(table):
It would likely be better as something like:
for row in table:
Or, if for some reason you really need the index, then:
for i, row in enumerate(table):
Example with looping on length removed:
So removing i
, and looping on table
, we get:
len_of_longest_name = 0
for row in table:
if len_of_longest_name < len(row[1]):
len_of_longest_name = len(row[1])
Use builtin functions.
Python have a max()
function. Using max()
, the example becomes:
len_of_longest_name = 0
for row in table:
len_of_longest_name = max(len_of_longest_name, len(row[1]))
Comprehensions:
Since max()
can take a comprehension the example loop can be reduced to:
len_of_longest_name = max(len(row[1]) for row in table)
That is six lines of code reduced to one.
add a comment |Â
up vote
3
down vote
Python has many great ways to iterate. In general if you find yourself looping on an integer, like in the following code, there is a good chance you are doing it wrong. It is generally better to iterate on the data structure itself.
Sample code:
I will use this loop as an example:
len_of_longest_name = 0
i = 0
while i < len(table):
if len_of_longest_name < len(table[i][1]):
len_of_longest_name = len(table[i][1])
i += 1
Don't iterate on the length of a data structure:
This is probably not what you want:
while i < len(table):
It would likely be better as something like:
for row in table:
Or, if for some reason you really need the index, then:
for i, row in enumerate(table):
Example with looping on length removed:
So removing i
, and looping on table
, we get:
len_of_longest_name = 0
for row in table:
if len_of_longest_name < len(row[1]):
len_of_longest_name = len(row[1])
Use builtin functions.
Python have a max()
function. Using max()
, the example becomes:
len_of_longest_name = 0
for row in table:
len_of_longest_name = max(len_of_longest_name, len(row[1]))
Comprehensions:
Since max()
can take a comprehension the example loop can be reduced to:
len_of_longest_name = max(len(row[1]) for row in table)
That is six lines of code reduced to one.
add a comment |Â
up vote
3
down vote
up vote
3
down vote
Python has many great ways to iterate. In general if you find yourself looping on an integer, like in the following code, there is a good chance you are doing it wrong. It is generally better to iterate on the data structure itself.
Sample code:
I will use this loop as an example:
len_of_longest_name = 0
i = 0
while i < len(table):
if len_of_longest_name < len(table[i][1]):
len_of_longest_name = len(table[i][1])
i += 1
Don't iterate on the length of a data structure:
This is probably not what you want:
while i < len(table):
It would likely be better as something like:
for row in table:
Or, if for some reason you really need the index, then:
for i, row in enumerate(table):
Example with looping on length removed:
So removing i
, and looping on table
, we get:
len_of_longest_name = 0
for row in table:
if len_of_longest_name < len(row[1]):
len_of_longest_name = len(row[1])
Use builtin functions.
Python have a max()
function. Using max()
, the example becomes:
len_of_longest_name = 0
for row in table:
len_of_longest_name = max(len_of_longest_name, len(row[1]))
Comprehensions:
Since max()
can take a comprehension the example loop can be reduced to:
len_of_longest_name = max(len(row[1]) for row in table)
That is six lines of code reduced to one.
Python has many great ways to iterate. In general if you find yourself looping on an integer, like in the following code, there is a good chance you are doing it wrong. It is generally better to iterate on the data structure itself.
Sample code:
I will use this loop as an example:
len_of_longest_name = 0
i = 0
while i < len(table):
if len_of_longest_name < len(table[i][1]):
len_of_longest_name = len(table[i][1])
i += 1
Don't iterate on the length of a data structure:
This is probably not what you want:
while i < len(table):
It would likely be better as something like:
for row in table:
Or, if for some reason you really need the index, then:
for i, row in enumerate(table):
Example with looping on length removed:
So removing i
, and looping on table
, we get:
len_of_longest_name = 0
for row in table:
if len_of_longest_name < len(row[1]):
len_of_longest_name = len(row[1])
Use builtin functions.
Python have a max()
function. Using max()
, the example becomes:
len_of_longest_name = 0
for row in table:
len_of_longest_name = max(len_of_longest_name, len(row[1]))
Comprehensions:
Since max()
can take a comprehension the example loop can be reduced to:
len_of_longest_name = max(len(row[1]) for row in table)
That is six lines of code reduced to one.
answered Jan 17 at 4:35
Stephen Rauch
3,53551430
3,53551430
add a comment |Â
add a comment |Â
up vote
2
down vote
Starting from what @Stephen Rauch said in his answer, you can greatly simplify your code.
You should definitely take a look at
str.join
,enumerate
,zip
and why you should not do string addition when concatenating many (not short) strings.I would first compute all column lengths (not just the two you calculate, relying on the fact that the other lengths are the same across rows). For this you can use nested list comprehensions.
I would declare the repeatedly re-used strings which make the table frame only once, instead of building them every loop iteration.
Finally, I would put this into a function to make it re-usable and add a
if __name__ == "__main__":
guard to allow importing this function from another script without running the code.
def data_table(table)
column_lens = [max(len(row[i]) for row in table)
for i in range(len(table[0]))]
# constructing string
separator = " | ".join("-" * (column_len - 2) for column_len in column_lens)
header = "/ " + separator + " \"
row_separator = "| " + separator + " |"
footer = "\ " + separator + " /"
new_table = [header]
for i, row in enumerate(table):
new_row = "|".join(column + " " * (column_len - len(column))
for column, column_len in zip(row, column_lens))
new_table.append("|" + new_row + "|")
if i < len(table) - 1:
new_table.append(row_separator)
new_table.append(footer)
return "n".join(new_table)
if __name__ == "__main__":
table = data_manager.get_table_from_file('games.csv')
print(data_table(table))
This prints for example:
/ ------ | --------------------------------- | -------------- | |
|kH34Ju%&|Age of Empires II: The Age of Kings|Ensemble Studios|32|32|
| ------ | --------------------------------- | -------------- | | |
|kH34*&23|Age of Empires I |Ensemble Studios|32|32|
------ | --------------------------------- | -------------- | | /
Note that this is a slightly different format (it has no sub-cells, as you do in your last two columns). Also note that if a column contains only cells of width 1 or 0, then the header and the table will be misaligned (since the header and footer row is at least 2 characters wide for each column.
Compared to your code, this has the great advantage that it works for every table that is defined as a list of lists.
add a comment |Â
up vote
2
down vote
Starting from what @Stephen Rauch said in his answer, you can greatly simplify your code.
You should definitely take a look at
str.join
,enumerate
,zip
and why you should not do string addition when concatenating many (not short) strings.I would first compute all column lengths (not just the two you calculate, relying on the fact that the other lengths are the same across rows). For this you can use nested list comprehensions.
I would declare the repeatedly re-used strings which make the table frame only once, instead of building them every loop iteration.
Finally, I would put this into a function to make it re-usable and add a
if __name__ == "__main__":
guard to allow importing this function from another script without running the code.
def data_table(table)
column_lens = [max(len(row[i]) for row in table)
for i in range(len(table[0]))]
# constructing string
separator = " | ".join("-" * (column_len - 2) for column_len in column_lens)
header = "/ " + separator + " \"
row_separator = "| " + separator + " |"
footer = "\ " + separator + " /"
new_table = [header]
for i, row in enumerate(table):
new_row = "|".join(column + " " * (column_len - len(column))
for column, column_len in zip(row, column_lens))
new_table.append("|" + new_row + "|")
if i < len(table) - 1:
new_table.append(row_separator)
new_table.append(footer)
return "n".join(new_table)
if __name__ == "__main__":
table = data_manager.get_table_from_file('games.csv')
print(data_table(table))
This prints for example:
/ ------ | --------------------------------- | -------------- | |
|kH34Ju%&|Age of Empires II: The Age of Kings|Ensemble Studios|32|32|
| ------ | --------------------------------- | -------------- | | |
|kH34*&23|Age of Empires I |Ensemble Studios|32|32|
------ | --------------------------------- | -------------- | | /
Note that this is a slightly different format (it has no sub-cells, as you do in your last two columns). Also note that if a column contains only cells of width 1 or 0, then the header and the table will be misaligned (since the header and footer row is at least 2 characters wide for each column.
Compared to your code, this has the great advantage that it works for every table that is defined as a list of lists.
add a comment |Â
up vote
2
down vote
up vote
2
down vote
Starting from what @Stephen Rauch said in his answer, you can greatly simplify your code.
You should definitely take a look at
str.join
,enumerate
,zip
and why you should not do string addition when concatenating many (not short) strings.I would first compute all column lengths (not just the two you calculate, relying on the fact that the other lengths are the same across rows). For this you can use nested list comprehensions.
I would declare the repeatedly re-used strings which make the table frame only once, instead of building them every loop iteration.
Finally, I would put this into a function to make it re-usable and add a
if __name__ == "__main__":
guard to allow importing this function from another script without running the code.
def data_table(table)
column_lens = [max(len(row[i]) for row in table)
for i in range(len(table[0]))]
# constructing string
separator = " | ".join("-" * (column_len - 2) for column_len in column_lens)
header = "/ " + separator + " \"
row_separator = "| " + separator + " |"
footer = "\ " + separator + " /"
new_table = [header]
for i, row in enumerate(table):
new_row = "|".join(column + " " * (column_len - len(column))
for column, column_len in zip(row, column_lens))
new_table.append("|" + new_row + "|")
if i < len(table) - 1:
new_table.append(row_separator)
new_table.append(footer)
return "n".join(new_table)
if __name__ == "__main__":
table = data_manager.get_table_from_file('games.csv')
print(data_table(table))
This prints for example:
/ ------ | --------------------------------- | -------------- | |
|kH34Ju%&|Age of Empires II: The Age of Kings|Ensemble Studios|32|32|
| ------ | --------------------------------- | -------------- | | |
|kH34*&23|Age of Empires I |Ensemble Studios|32|32|
------ | --------------------------------- | -------------- | | /
Note that this is a slightly different format (it has no sub-cells, as you do in your last two columns). Also note that if a column contains only cells of width 1 or 0, then the header and the table will be misaligned (since the header and footer row is at least 2 characters wide for each column.
Compared to your code, this has the great advantage that it works for every table that is defined as a list of lists.
Starting from what @Stephen Rauch said in his answer, you can greatly simplify your code.
You should definitely take a look at
str.join
,enumerate
,zip
and why you should not do string addition when concatenating many (not short) strings.I would first compute all column lengths (not just the two you calculate, relying on the fact that the other lengths are the same across rows). For this you can use nested list comprehensions.
I would declare the repeatedly re-used strings which make the table frame only once, instead of building them every loop iteration.
Finally, I would put this into a function to make it re-usable and add a
if __name__ == "__main__":
guard to allow importing this function from another script without running the code.
def data_table(table)
column_lens = [max(len(row[i]) for row in table)
for i in range(len(table[0]))]
# constructing string
separator = " | ".join("-" * (column_len - 2) for column_len in column_lens)
header = "/ " + separator + " \"
row_separator = "| " + separator + " |"
footer = "\ " + separator + " /"
new_table = [header]
for i, row in enumerate(table):
new_row = "|".join(column + " " * (column_len - len(column))
for column, column_len in zip(row, column_lens))
new_table.append("|" + new_row + "|")
if i < len(table) - 1:
new_table.append(row_separator)
new_table.append(footer)
return "n".join(new_table)
if __name__ == "__main__":
table = data_manager.get_table_from_file('games.csv')
print(data_table(table))
This prints for example:
/ ------ | --------------------------------- | -------------- | |
|kH34Ju%&|Age of Empires II: The Age of Kings|Ensemble Studios|32|32|
| ------ | --------------------------------- | -------------- | | |
|kH34*&23|Age of Empires I |Ensemble Studios|32|32|
------ | --------------------------------- | -------------- | | /
Note that this is a slightly different format (it has no sub-cells, as you do in your last two columns). Also note that if a column contains only cells of width 1 or 0, then the header and the table will be misaligned (since the header and footer row is at least 2 characters wide for each column.
Compared to your code, this has the great advantage that it works for every table that is defined as a list of lists.
answered Jan 17 at 14:32
Graipher
20.5k43081
20.5k43081
add a comment |Â
add a comment |Â
up vote
-1
down vote
Thanks for your answers. I wrote this:
import data_manager
def table_lines():
string = ""
for indices in range(0, len(max_len)):
value = max_len[indices]
string += "|" + (value * "-")
string += "|"
return string
def data_lines(table):
data_string = "|"
for row in table:
for indices in range(0, len(row)):
if len(row[indices]) < max_len[indices]:
data_string += row[indices] + ((max_len[indices] - len(row[indices] )) * " ") + "|"
else:
data_string += row[indices] + "|"
print(table_lines())
print(data_string)
data_string = "|"
def get_longest(table):
for row in table:
value_len =
for element in row:
value_len.append(len(element))
# for debug print(row)
values_len.append(value_len)
# for debug print(values_len)
for row in values_len:
for indices in range(0, len(row)):
try:
if row[indices] > max_len[indices]:
max_len[indices] = row[indices]
except IndexError:
max_len.append(row[indices])
The output looks like this:
Now I will work on fixing a corners of table.
Thanks once more!
1
You should not be (implicitly even) using globals like you do. Instead return the objects you create inside your functions and pass them as arguments to the functions that need them.
â Graipher
Jan 17 at 15:53
add a comment |Â
up vote
-1
down vote
Thanks for your answers. I wrote this:
import data_manager
def table_lines():
string = ""
for indices in range(0, len(max_len)):
value = max_len[indices]
string += "|" + (value * "-")
string += "|"
return string
def data_lines(table):
data_string = "|"
for row in table:
for indices in range(0, len(row)):
if len(row[indices]) < max_len[indices]:
data_string += row[indices] + ((max_len[indices] - len(row[indices] )) * " ") + "|"
else:
data_string += row[indices] + "|"
print(table_lines())
print(data_string)
data_string = "|"
def get_longest(table):
for row in table:
value_len =
for element in row:
value_len.append(len(element))
# for debug print(row)
values_len.append(value_len)
# for debug print(values_len)
for row in values_len:
for indices in range(0, len(row)):
try:
if row[indices] > max_len[indices]:
max_len[indices] = row[indices]
except IndexError:
max_len.append(row[indices])
The output looks like this:
Now I will work on fixing a corners of table.
Thanks once more!
1
You should not be (implicitly even) using globals like you do. Instead return the objects you create inside your functions and pass them as arguments to the functions that need them.
â Graipher
Jan 17 at 15:53
add a comment |Â
up vote
-1
down vote
up vote
-1
down vote
Thanks for your answers. I wrote this:
import data_manager
def table_lines():
string = ""
for indices in range(0, len(max_len)):
value = max_len[indices]
string += "|" + (value * "-")
string += "|"
return string
def data_lines(table):
data_string = "|"
for row in table:
for indices in range(0, len(row)):
if len(row[indices]) < max_len[indices]:
data_string += row[indices] + ((max_len[indices] - len(row[indices] )) * " ") + "|"
else:
data_string += row[indices] + "|"
print(table_lines())
print(data_string)
data_string = "|"
def get_longest(table):
for row in table:
value_len =
for element in row:
value_len.append(len(element))
# for debug print(row)
values_len.append(value_len)
# for debug print(values_len)
for row in values_len:
for indices in range(0, len(row)):
try:
if row[indices] > max_len[indices]:
max_len[indices] = row[indices]
except IndexError:
max_len.append(row[indices])
The output looks like this:
Now I will work on fixing a corners of table.
Thanks once more!
Thanks for your answers. I wrote this:
import data_manager
def table_lines():
string = ""
for indices in range(0, len(max_len)):
value = max_len[indices]
string += "|" + (value * "-")
string += "|"
return string
def data_lines(table):
data_string = "|"
for row in table:
for indices in range(0, len(row)):
if len(row[indices]) < max_len[indices]:
data_string += row[indices] + ((max_len[indices] - len(row[indices] )) * " ") + "|"
else:
data_string += row[indices] + "|"
print(table_lines())
print(data_string)
data_string = "|"
def get_longest(table):
for row in table:
value_len =
for element in row:
value_len.append(len(element))
# for debug print(row)
values_len.append(value_len)
# for debug print(values_len)
for row in values_len:
for indices in range(0, len(row)):
try:
if row[indices] > max_len[indices]:
max_len[indices] = row[indices]
except IndexError:
max_len.append(row[indices])
The output looks like this:
Now I will work on fixing a corners of table.
Thanks once more!
answered Jan 17 at 15:21
Voyt
392
392
1
You should not be (implicitly even) using globals like you do. Instead return the objects you create inside your functions and pass them as arguments to the functions that need them.
â Graipher
Jan 17 at 15:53
add a comment |Â
1
You should not be (implicitly even) using globals like you do. Instead return the objects you create inside your functions and pass them as arguments to the functions that need them.
â Graipher
Jan 17 at 15:53
1
1
You should not be (implicitly even) using globals like you do. Instead return the objects you create inside your functions and pass them as arguments to the functions that need them.
â Graipher
Jan 17 at 15:53
You should not be (implicitly even) using globals like you do. Instead return the objects you create inside your functions and pass them as arguments to the functions that need them.
â Graipher
Jan 17 at 15:53
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185238%2fdrawing-a-table-for-data-from-file%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
what was the source data like?
â hjpotter92
Jan 16 at 18:44
kH34Ju#&;Age of Empires II: The Age of Kings;Ensemble Studios;32;32n Every record looks like this, ";" is a separator.
â Voyt
Jan 16 at 19:10
2
Have you considered using a package such as terminaltables?
â 200_success
Jan 16 at 20:09
what is
data_manager
?â Stephen Rauch
Jan 17 at 4:17
data_manager is a module that reads from file and returns list of lines in one variable
â Voyt
Jan 17 at 7:56