将CSV输入文件打印到列/行表中 [英] Print csv input file into a table of columns/rows

查看:89
本文介绍了将CSV输入文件打印到列/行表中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个程序,该程序(除其他外)将输入文件('table1.txt')打印为以下所示格式.

I am trying to write a program that (among other things), prints an input file ('table1.txt') into the format seen below.

其中diff是每行第三和第四值之间的差.

Where diff is the difference between the 3rd and 4th value of each line.

我想我已经弄清了基本思路,然后尝试做:

I think I have the basic idea figured out and I tried doing:

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()

但是会导致操作数类型错误.我想我只需要更改对文件中的项目进行迭代的方式,但是我不知道该怎么做.

But it results in a operand type error. I think I just have to change the way I iterate over the items in the file but I do not know how.

推荐答案

为此,您绝对应该使用csv模块.它允许您遍历行和值(本质上是构建一个漂亮的列表列表"). csv还有一个DictWriter对象,可以很好地将这些数据吐到文件中,但是实际显示却有些不同.让我们先来看一下csv的构建.

You should definitely use the csv module for this. It allows you to iterate through rows and values (essentially building a fancy "list of lists"). csv also has a DictWriter object that would work well to spit this data into a file, but actually displaying it is a little different. Let's look at building the csv first.

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语句以显示它就非常容易了.我们可以使用字符串模板来很好地做到这一点.

This should give you a csv file (at path/to/output.csv) that has the data in the format you requested. At this point it's pretty easy to just pull the data and run print statements to display it. We can use string templating to do this nicely.

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)魔术成语进行过多介绍.换句话说

It's worth stopping here to look at this magic. I won't go too far into the columns = zip(*pre_process) magic idiom, other than noting that it turns rows of columns into columns of rows. In other words

zip(*[[1, 2, 3],
      [4, 5, 6],
      [7, 8, 9]])

成为

     [[1, 4, 7],
      [2, 5, 8],
      [3, 6, 9]]

此后,我们仅使用字典理解来构建{'team_length': value, 'point_length': ...}等,我们可以将其输入到模板程序中以使字段宽度为正确的大小.

after that we're just using a dictionary comprehension to build {'team_length': value, 'point_length': ...} etc that we can feed into our templater to make the field widths the right size.

在该词典中我们还需要idx_length!我们只能通过len(rows) // 10进行计算.不幸的是,我们已经用尽了迭代器,没有更多数据了.这需要重新设计!我实际上没有对此进行很好的计划,但是看看这些在编码过程中是如何发生的是很好的例证.

We also need idx_length in that dictionary! We can only calculate that by doing len(rows) // 10. Unfortunately we've exhausted our iterator and we don't have any more data. This calls for a redesign! I actually didn't plan this out well, but seeing how these things happen in the course of coding is good illustration.

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表.正是您想要做的

Batteries (almost) included

But let's not forget that Python has an extensive selection of 3rd party modules. One does exactly what you need. tabulate will take well-formed tabular data and spit out a pretty printed ascii table for it. Exactly what you're trying to do

从pypi命令行安装

$ pip install tabulate

然后导入您的显示文件并打印.

Then import in your display file and print.

import tabulate

with open('path/to/output.csv') as inf:
    print(tabulate(inf, headers="firstrow"))

或者直接从输入跳到打印:

Or skipping straight from input to print:

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))

这篇关于将CSV输入文件打印到列/行表中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆