我正在尝试编写一个程序(除其他外),将输入文件(' table1.txt')打印成下面所示的格式。
其中diff是每行第3和第4个值之间的差异。
我认为我已经找到了基本想法,我尝试过:
f = open("table1.txt",'r')
for aline in f:
values = aline.split(',')
print('Team:',values[0],', Points:',values[1],', Diff:',values[2]-values[3],'Goals:',values[2])
f.close()
但它会导致操作数类型错误。我想我只需要改变迭代文件中项目的方式,但我不知道如何。
答案 0 :(得分:6)
你绝对应该使用csv
模块。它允许您遍历行和值(基本上构建一个奇特的#34;列表列表")。 csv
还有一个DictWriter
对象可以很好地将这些数据吐入文件,但实际显示它有点不同。让我们先看看构建csv。
import csv
import operator
with open('path/to/file.txt') as inf,
open('path/to/output.csv', 'wb') as outf:
reader = sorted(csv.reader(inf), key=operator.itemgetter(1)
# sort the original data by the `points` column
header = ['Team', 'Points', 'Diff', 'Goals']
writer = csv.DictWriter(outf, fieldnames=header)
writer.writeheader() # writes in the fieldnames
for row in reader:
if not len(row) == 4:
break # This is probably not a useful row
teamname, points, home_g, away_g = row
writer.writerow({'Team': teamname,
'Points': points,
'Diff': home_g - away_g,
'Goals': "{:>2} : {:2}".format(home_g, away_g)
})
这应该为您提供一个csv文件(path/to/output.csv
),其中包含您请求的格式的数据。此时,只需拉取数据并运行print
语句即可显示它。我们可以使用字符串模板来很好地完成这项工作。
import itertools
row_template = """\
{{0:{idx_length}}}{{<1:{teamname_length}}}{{>2:{point_length}}}{{>3:{diff_length}}}{{=4:{goals_length}}}"""
with open('path/to/output.csv') as inf: # same filename we used before
reader = csv.reader(inf) # no need to sort it this time!
pre_process, reader = itertools.tee(reader)
# we need to get max lengths for each column to build our table, so
# we will need to iterate through twice!
columns = zip(*pre_process) # this is magic
col_widths = {k: len(max(col, key=len)) for k,col in zip(
['teamname_length', 'point_length', 'diff_length', 'goals_length'],
columns)}
值得停下来看看这个魔法。除了注意到它将行列变成行列之外,我不会进入columns = zip(*pre_process)
魔法习语。换句话说
zip(*[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
变为
[[1, 4, 7],
[2, 5, 8],
[3, 6, 9]]
之后我们只是使用字典理解来构建{'team_length': value, 'point_length': ...}
等我们可以提供给我们的模板以使字段宽度合适。
我们还需要该词典中的idx_length
!我们只能通过len(rows) // 10
计算出来。不幸的是,我们已经耗尽了我们的迭代器,而且我们还没有更多的数据。这需要重新设计!我实际上并没有很好地计划好这一点,但在编码过程中看到这些事情是如何发生的那样很好。
import itertools
row_template = """\
{{0:{idx_length}}}{{<1:{teamname_length}}}{{>2:{point_length}}}{{>3:{diff_length}}}{{=4:{goals_length}}}"""
with open('path/to/output.csv') as inf: # same filename we used before
reader = csv.reader(inf)
pre_process, reader = itertools.tee(reader)
# fun with pre-processing for field length!
columns = zip(*pre_process)
keys = ['teamname_length', 'point_length', 'diff_length', 'goals_length']
col_widths = {k:0 for k in keys}
for key, column in zip(keys, columns):
col_widths['idx_length'] = max([col_widths['idx_length'], len(column) // 10 + 1])
col_widths[key] = max((col_widths[key],max([len(c) for c in column)))
col_widths['idx_length'] += 1 # to account for the trailing period
row_format = row_template.format(**col_widths)
# puts those field widths in place
header = next(reader)
print(row_format("", *header)) # no number in the header!
for idx, row in enumerate(reader, start=1): # let's do it!
print(row_format("{}.".format(idx), *row))
但是,不要忘记Python有广泛的第三方模块选择。一个人完全符合你的需要。 tabulate
将获取格式良好的表格数据并为其喷出漂亮的ascii表格。正是你要做的事情
从命令行的pypi安装
$ pip install tabulate
然后导入您的显示文件并打印。
import tabulate
with open('path/to/output.csv') as inf:
print(tabulate(inf, headers="firstrow"))
或直接从输入跳到打印:
import csv
import operator
import tabulate
with open('path/to/file.txt') as inf:
reader = sorted(csv.reader(inf), key=operator.itemgetter(1))
headers = next(reader)
print(tabulate([(row[0], row[1], row[2]-row[3],
"{:>2} : {:2}".format(row[2], row[3])) for row in reader],
headers=headers))
答案 1 :(得分:2)
在执行减法时尝试将值[2]和值[3]转换为int:
', Diff:', int(values[2])-int(values[3])
答案 2 :(得分:2)
刚试过,如果加载txt文件,CSV模块就不在乎了。
我会使用with open ... as
方法,因为它更干净,之后你不必关闭f。
import csv
with open("importCSV.txt",'r') as f:
rowReader = csv.reader(f, delimiter=',')
#next(rowReader) -use this if your txt file has a header strings as column names
for values in rowReader:
print'Team:',values[0],', Points:',values[1],', Diff:',int(values[2])-int(values[3]),'Goals:',values[2]