如何确保将从CSV读取的所有项目都解析为字典?

时间:2014-02-23 16:29:01

标签: python csv dictionary

我有一个大的CSV文件,我从中读取一些数据并将该数据添加到字典中。我的CSV文件大约有360000行,我的字典长度只有5700.我知道我的CSV有很多重复项,但我希望大约有50000行。我知道Python字典对大小没有限制。我的代码读取文件中的所有360000个条目,将其写入另一个文件并终止。所有这些处理在大约2秒内完成,没有任何例外。我如何确定我处理的CSV中的所有项目实际上都已添加到字典中?

我使用的代码如下:

with open("read.csv", 'rb') as input1:
    with open("write.csv", 'wb') as output1:
        reader = csv.reader(input1, delimiter="\t")
        writer = csv.writer(output1, delimiter="\t")
        #Just testing if my program reads the whole CSV file
        for row in reader:
            count += 1
        print count        # Gives 360000
        input1.seek(0)
        for row in reader:
            #print row[1] + "\t" + row[2]
            dict1.update({row[1] : [ row[2], row[0] ]}) 
        print len(dict1)   # Gives 5700
        for key in dict1:
            ext_id = key
            list1 = dict1[key]
            name = list1[0]
            url = list1[1]
            writer.writerow([ext_id, name, url])

修改

我不确定人们是否理解我想要做什么以及这将如何相关,但我仍然会解释。

我的CSV文件每行有3列。他们的格式如下:

URL+unique value | unique value | some name

但是,这些行在CSV中是重复的,我想要另一个只有行没有任何副本的CSV。

3 个答案:

答案 0 :(得分:3)

词典中的键是row[1]。字典的大小取决于输入中此字段的不同值。行(row[2], row[0])的其余部分在行之间是否不同并不重要。

示例:

a,foo,1
b,bar,2
c,foo,3
d,baz,4

如果第一个字段(索引3)用作键,将导致长度为1的字典。结果将是:

{'foo':['3', 'c'],
 'bar':['2', 'b'],
 'baz':['4', 'd']}

第一行将被覆盖。当然,“订单”可能会有所不同,因为字典没有订单。

答案 1 :(得分:2)

编辑:如果您只是检查唯一性,则无需将其放入字典(专为快速查找和分组而设计)中。请改用此处set

out_ = set()

for row in reader:
    out_.add(tuple(row))
# csv.reader may iterate through tuples already, I don't know! If so
# there's obviously no reason to cast it as one. Do:
## print(type(reader[0]))
# to find out.

for row in out_:
    writer.writerow([row[1], row[0], row[2]])

这是我能想到的最快的检查。

set_headers = {row[1] for row in reader}

这是一个包含CSV中所有行的所有第2列(也就是row[1])的集合。您可能知道,集合不能包含重复项,因此这将为您提供每行标题列中的UNIQUE值。

dict.update替换值以来,这正是您将len(dict1)看到的,实际上是len(set_headers) == len(dict1)。每次迭代一行时,dict.update都会将密钥row[1]的值更改为(row[0], row[2])。如果你不关心早期的价值观,那可能就好了,但我不认为这是真的。

相反,这样做:

for row in reader:
    dict1.setdefault(row[1],[]).append((row[0],row[1]))

这将最终成为:

dict1 = {"foo": [(row1_col0,row1_col2),(row3_col0,row3_col2)],
         "baz": [(row2_col0,row2_col2)]}

来自输入:

row1_col0, foo, row1_col2
row2_col0, baz, row2_col2
row3_col0, foo, row3_col2

现在你可以这样做,例如:

for header in dict1:
    for row in header:
        print("{}\t{}".format(row[0],row[1]))

答案 2 :(得分:1)

确保获得所有内容的最简单方法是添加2个测试列表。添加:test1,test2 = [],[],然后在更新字典后立即添加test1.append(row [1]),然后如果row [1]不在test2中:test2.append(row [1])。然后你可以打印两个列表的长度,看看test2的长度是否与你的字典相同,test1的长度和输入csv的长度相同。

with open("read.csv", 'rb') as input1:
    with open("write.csv", 'wb') as output1:
        reader = csv.reader(input1, delimiter="\t")
        writer = csv.writer(output1, delimiter="\t")
        #Just testing if my program reads the whole CSV file
        test1,test2=[],[]
        for row in reader:
            count += 1
        print count        # Gives 360000
        input1.seek(0)
        for row in reader:
            #print row[1] + "\t" + row[2]
            dict1.update({row[1] : [ row[2], row[0] ]})
            test1.append(row[1])
            if row[1] not in test2: test2.append(row[1])
        print 'dictionary length:', len(dict1)   # Gives 5700
        print 'test 1 length (total values):',len(test1)
        print 'test2 length (unique key values):',len(test2)
        for key in dict1:
            ext_id = key
            list1 = dict1[key]
            name = list1[0]
            url = list1[1]
            writer.writerow([ext_id, name, url])