使用Python将csv文件转换为元组列表

16

我需要使用一个包含4列的csv文件:品牌、价格、重量和类别。

类别有橙子、苹果、梨和李子。

参数:我需要选择最可能达到的重量,但必须通过选择1个橙子、2个梨子、3个苹果和1个李子来保持不超过20美元的预算。我不能重复选择同一种水果的品牌(例如选择相同品牌的苹果3次等)。

我可以通过Python打开和读取csv文件,但我不确定如何从csv文件中创建字典或元组列表?

为了更清楚地说明,这里是数据的一个想法。

Brand, Price, Weight, Type
brand1, 6.05, 3.2, orange
brand2, 8.05, 5.2, orange
brand3, 6.54, 4.2, orange
brand1, 6.05, 3.2, pear
brand2, 7.05, 3.6, pear
brand3, 7.45, 3.9, pear
brand1, 5.45, 2.7, apple
brand2, 6.05, 3.2, apple
brand3, 6.43, 3.5, apple
brand4, 7.05, 3.9, apple
brand1, 8.05, 4.2, plum
brand2, 3.05, 2.2, plum

这是我现在拥有的所有内容:

import csv
test_file = 'testallpos.csv'
csv_file = csv.DictReader(open(test_file, 'rb'), ["brand"], ["price"], ["weight"], ["type"])

是的,我收到了一些反馈意见,需要更改问题的标题和清晰度。这样更具体,可以更好地理解问题。 - Sean
请仅返回翻译文本:然后请删除旧问题,重复讨论相同主题没有意义。同时,请发布您迄今为止的代码,这将使人们更有可能为您提供帮助。 - Tymoteusz Paul
是的,我之前删除了它,不确定要多久才能删除。我是这个网站的新手,抱歉! - Sean
所有字段名称都需要放在一个列表中,如下所示:csv.DictReader(open(test_file, 'rb'), ["brand", "price", "weight", "type"]) - Asad Saeeduddin
你的文件是否像你的示例一样有空白? - dawg
我的文件不是.csv格式的,只是为了可读性而这样命名的。把空格替换成逗号就是csv格式了。 - Sean
2个回答

31

你可以思考一下:

import csv

def fitem(item):
    item=item.strip()
    try:
        item=float(item)
    except ValueError:
        pass
    return item        

with open('/tmp/test.csv', 'r') as csvin:
    reader=csv.DictReader(csvin)
    data={k.strip():[fitem(v)] for k,v in reader.next().items()}
    for line in reader:
        for k,v in line.items():
            k=k.strip()
            data[k].append(fitem(v))

print data 

输出:

{'Price': [6.05, 8.05, 6.54, 6.05, 7.05, 7.45, 5.45, 6.05, 6.43, 7.05, 8.05, 3.05],
 'Type': ['orange', 'orange', 'orange', 'pear', 'pear', 'pear', 'apple', 'apple', 'apple', 'apple', 'plum', 'plum'], 
 'Brand': ['brand1', 'brand2', 'brand3', 'brand1', 'brand2', 'brand3', 'brand1', 'brand2', 'brand3', 'brand4', 'brand1', 'brand2'], 
 'Weight': [3.2, 5.2, 4.2, 3.2, 3.6, 3.9, 2.7, 3.2, 3.5, 3.9, 4.2, 2.2]}

如果您希望将csv文件直接按行作为元组:

import csv
with open('/tmp/test.csv') as f:
    data=[tuple(line) for line in csv.reader(f)]

print data
# [('Brand', ' Price', ' Weight', ' Type'), ('brand1', ' 6.05', ' 3.2', ' orange'), ('brand2', ' 8.05', ' 5.2', ' orange'), ('brand3', ' 6.54', ' 4.2', ' orange'), ('brand1', ' 6.05', ' 3.2', ' pear'), ('brand2', ' 7.05', ' 3.6', ' pear'), ('brand3', ' 7.45', ' 3.9', ' pear'), ('brand1', ' 5.45', ' 2.7', ' apple'), ('brand2', ' 6.05', ' 3.2', ' apple'), ('brand3', ' 6.43', ' 3.5', ' apple'), ('brand4', ' 7.05', ' 3.9', ' apple'), ('brand1', ' 8.05', ' 4.2', ' plum'), ('brand2', ' 3.05', ' 2.2', ' plum')]

你的回答最后一部分正是我所需要的。谢谢! - GollyJer

2
import csv
with open("some.csv") as f:
       r = csv.reader(f)
       print filter(None,r)

或者使用列表推导式。
import csv
with open("some.csv") as f:
       r = csv.reader(f)
       print [row for row in r if row]

与之相比
In [3]: N = 100000

In [4]: the_list = [randint(0,3) for _ in range(N)]

In [5]: %timeit filter(None,the_list)
1000 loops, best of 3: 1.91 ms per loop

In [6]: %timeit [i for i in the_list if i]
100 loops, best of 3: 4.01 ms per loop

[编辑] 由于您的实际输出没有空行,因此您不需要列表推导式或筛选器,您只需说list(r)

最终答案不包含空行

import csv
with open("some.csv") as f:
       print list(csv.reader(f))

如果您想要字典,可以执行以下操作:
import csv
with open("some.csv") as f:
       reader = list(csv.reader(f))
       print [dict(zip(reader[0],x)) for x in reader]
       #or
       print map(lambda x:dict(zip(reader[0],x)), reader)

1
不要使用 filter(bool, ...),而应当使用 filter(None, ...)filter() 有一种特殊情况可以避免过度转换为 bool(因为调用 bool 的结果也会被检查真实性)。同时,不要使用 filter(..., list(seq)),而应该使用 filter(..., seq),filter 知道如何迭代序列,中间的列表只会浪费空间。 - SingleNegationElimination
是的,我不确定在列表转换方面我当时在想什么...我不知道 None 过滤器。 - Joran Beasley
无用的使用filter,你可以直接使用print [e for e in r],这样更快且更易读。-1 - user648852
原帖作者表示他的CSV文件中没有空行。他发布的信息是错误的。如果有空行--你才有观点... - user648852
谢谢你的帮助!现在我已经把CSV文件转换成可以操作的格式,正在进行一些试验。 - Sean
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接