使用Python 3.3.0,我从csv文件创建了一个“字典”(标题:ID;Col1;Col2;Col3;Col4;Col5
):
ID;Col1;Col2;Col3;Col4;Col5
15345;1;1;nnngngn;vhrhtnz;latest
12345;12;8;gnrghrtthr;tznhltrnhklr;latest
90834;3;4;something;nonsens;latest
12345;34;235;dontcare;muhaha;oldone
代码
file = "test.csv"
csv_file = csv.DictReader(open(file, 'r'), delimiter=';', quotechar='"')
我希望将ID = 12345的行复制到新词典中,而不是复制到文件中。 我真的习惯于复制到字典而不是列表中,因为我希望能够直接处理列名。 我这样做了
cewl = {}
for row in csv_file:
if row['ID'] == '12345':
cewl.update(row)
print(cewl)
输出是:
{'ID': '12345', 'Col1': '34', 'Col2': '235', 'Col3': 'dontcare', 'Col4': 'muhaha', 'Col5': 'oldone'}
我的问题: 只复制了ID = 12345的第二行,第一行被省略,我不知道为什么。
如果我通过复制到新列表(仅用于测试目的)来尝试此操作,那么一切正常:
cewl = []
for row in csv_file1:
if row['ID'] == '12345':
cewl.append(row)
print(cewl)
输出是:
[{'Col3': 'gnrghrtthr', 'Col2': '8', 'Col1': '12', 'Col5': 'latest', 'Col4': 'tznhltrnhklr', 'ID': '12345'},
{'Col3': 'dontcare', 'Col2': '235', 'Col1': '34', 'Col5': 'oldone', 'Col4': 'muhaha', 'ID': '12345'}]
我不知道为什么这不能通过复制到新词典中工作...似乎没有像.add或.append这样的方法用于dictreader。
如何在不遗漏任何行的情况下将数据复制到新词典中?
答案 0 :(得分:2)
预期产量是多少? dict
的行为完全正常;您使用新值替换每个键的值。
如果您希望每个匹配行的值为列表,则defaultdict
与list
工厂一起使用会更容易:
from collections import defaultdict
cewl = defaultdict(list)
for row in csv_file:
if row['ID'] == '12345':
for k, v in row.items():
cewl[k].append(v)
print(cewl)
输出:
defaultdict(<class 'list'>, {'Col1': ['12', '34'], 'ID': ['12345', '12345'], 'Col2': ['8', '235'], 'Col5': ['latest', 'oldone'], 'Col4': ['tznhltrnhklr', 'muhaha'], 'Col3': ['gnrghrtthr', 'dontcare']})
defaultdict
是dict
的子类,因此print(cewl['Col1'])
将打印['12', '34']
。
当您使用.update()
时,您可以有效地执行此操作:
for k, v in row.items():
cewl[k] = v
e.g。将cewl
中的每个键设置为正在处理的行中找到的值。处理最后一行时,它的值会覆盖先前行的值。
如果您只想过滤掉符合某个ID
条件的行,那么将它们添加到列表中就可以了。然后循环匹配的结果来处理它们:
for row in cewl:
# do something with matched row
或者您可以构建一个生成器过滤器,围绕DictReader()
进行过滤,以便为您进行过滤,因此您无需在内存中构建列表:
def rowfilter(reader, id):
for row in reader:
if row['ID'] == id:
yield row
for row in rowfilter(csv_file, '12345'):
# do something with matched row