按csv fi中的特定行组织和打印信息

2024-05-19 20:54:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我编写了一个代码,接收一些数据,最后得到一个csv文件,如下所示:

1,Steak,Martins
2,Fish,Martins
2,Steak,Johnsons
4,Veggie,Smiths
3,Chicken,Johnsons
1,Veggie,Johnsons

其中,第一列是数量,第二列是项目类型(在本例中是膳食),第三列是标识符(在本例中是姓氏)。我需要以特定方式将此信息打印到文本文件:

Martins
1 Steak
2 Fish
Johnsons
2 Steak
3 Chicken
1 Veggie
Smiths
4 Veggie

所以我要的是姓,然后是那家人点的菜。我写了下面的代码来实现这一点,但它似乎不太存在

import csv
orders = "orders.txt"
messy_orders = "needs_sorting.csv"

    with open(messy_orders, 'rb') as orders_for_sorting, open(orders, 'a') as final_orders_file:
        comp = []
        reader_sorting = csv.reader(orders_for_sorting)
        for row in reader_sorting:
            test_bit = [row[2]]
            if test_bit not in comp:
                comp.append(test_bit)
                final_orders_file.write(row[2])
                for row in reader_sorting:
                    if [row[2]] == test_bit:
                        final_orders_file.write(row[0], row[1])

            else:
                print "already here"
                continue

我的结论是

Martins
2 Fish

此外,我从来没有看到它打印“已经在这里”,虽然我认为我应该如果它工作正常。我怀疑正在发生的是程序经过第二个for循环,然后退出程序而不继续第一个循环。不幸的是,我不知道如何使它回到原来的循环,一旦它已经确定并打印了一个文件中的一个给定的姓的所有实例。我想我之所以这样设置它,是为了让我可以把姓氏写成标题。否则我就按姓氏对文件排序。请注意,在通过我的第一个程序运行订单之后,我成功地对所有内容进行了排序,使每一行都代表了该家庭该类型食物的完整数量(没有一行同时包含牛排和马丁酒的重复实例)


Tags: 文件csvtestforbitreaderroworders
2条回答

这是你用字典解决的问题;它将按文件的姓氏(姓氏)累积您的项目

你要做的第二件事是累积每种类型的食物的总数-记住你正在读取的数据是一个字符串,而不是一个可以添加的整数,所以你必须做一些转换

要将所有这些放在一起,请尝试以下代码段:

import csv

d = dict()

with open(r'd:/file.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        # if the family name doesn't
        # exist in our dictionary,
        # set it with a default value of a blank dictionary
        if row[2] not in d:
            d[row[2]] = dict()

        # If the meal type doesn't exist for this
        # family, set it up as a key in their dictionary
        # and set the value to int value of the count
        if row[1] not in d[row[2]]:
            d[row[2]][row[1]] = int(row[0])
        else:
            # Both the family and the meal already
            # exist in the dictionary, so just add the
            # count to the total
            d[row[2]][row[1]] += int(row[0])

一旦你运行了这个循环,d看起来是这样的:

{'Johnsons': {'Chicken': 3, 'Steak': 2, 'Veggie': 1},
 'Martins': {'Fish': 2, 'Steak': 1},
 'Smiths': {'Veggie': 4}}

现在只需打印出来:

for family,data in d.iteritems():
   print('{}'.format(family))
   for meal, total in data.iteritems():
       print('{} {}'.format(total, meal))

循环结束时,您将拥有:

Johnsons
3 Chicken
2 Steak
1 Veggie
Smiths
4 Veggie
Martins
2 Fish
1 Steak

稍后可以使用^{}来改进此代码段

第一次答复,所以这是一个开始。你考虑过跟踪订单然后写一份文件吗?我尝试了一些基于dict的方法,似乎效果不错。其想法是按姓氏编制索引,并存储一个包含订购数量和类型的配对列表

您可能还需要考虑代码的可读性—很难理解和调试。然而,我认为正在发生的是线

for line in reader_sorting:

遍历reader\u排序。读取第一个名字,提取姓氏,然后在reader\排序中再次进行迭代。这一次,您从第2行开始,姓氏匹配,并成功打印。行的其余部分不匹配,但您仍然遍历它们。现在您已经完成了对reader\排序的迭代,循环也完成了,即使在外部循环中您只读取了一行

一种解决方案是在outer for循环中创建另一个迭代器,而不是扩展循环所经过的迭代器。但是,您仍然需要处理重复计算的可能性,或者跟踪索引。另一种方法可能是在迭代时按族保留顺序

import csv

orders = {}

with open('needs_sorting.csv') as file:
    needs_sorting = csv.reader(file)
    for amount, meal, family in needs_sorting:
        if family not in orders:
            orders[family] = []            
        orders[family].append((amount, meal))

with open('orders.txt', 'a') as file:
    for family in orders:
        file.write('%s\n' % family)
        for amount, meal in orders[family]:
            file.write('%s %s\n' % (amount, meal))

相关问题 更多 >