在DictReader上使用Filter()
我刚开始学习Python,想弄明白怎么在csv.DictReader上使用filter函数来过滤csv文件中的行。filter()可以用在“可迭代对象”上,按照我的理解,DictReader符合这个定义。
但是当我尝试
f = open('file1.csv', 'r')
dialect = csv.Sniffer().sniff(f.read(1024))
f.seek(0)
reader = csv.DictReader(f, None, None, None, dialect)
filteredReader = filter(None, reader) #None will be replaced with my function
for i in filteredReader:
print(i)
时,我收到一个错误信息:TypeError: normcase() argument must be str or bytes, not 'DictReader'
。
请注意,我并不想在文件指针上进行过滤(例如这里),而是想在解析后的csv行上进行过滤。你知道怎么做到这一点吗?
2 个回答
0
使用DictReader时,过滤功能按你预期的那样工作。
假设你有一个这样的csv文件:
numeral, English, Spanish
1, one, uno
2, two, dos
3, three, tres
4, four, quatro
5, five, cinco
(注意第二列和第三列前面的空格)
而你只想要奇数行:
>>> with open('/tmp/nums.csv') as f:
... print filter(lambda d: int(d['numeral'])%2, csv.DictReader(f))
[{' English': ' one', 'numeral': '1', ' Spanish': ' uno'}, {' English': ' three', 'numeral': '3', ' Spanish': ' tres'}, {' English': ' five', 'numeral': '5', ' Spanish': ' cinco'}]
注意,前面的空格也被带到了我们的数据中。好吧,试试这样使用csv.Sniffer:
with open('/tmp/nums.csv') as f:
dialect = csv.Sniffer().sniff(f.read(1024))
f.seek(0)
print filter(lambda d: int(d['numeral'])%2, csv.DictReader(f, dialect=dialect))
# [{'numeral': '1', 'Spanish': 'uno', 'English': 'one'}, {'numeral': '3', 'Spanish': 'tres', 'English': 'three'}, {'numeral': '5', 'Spanish': 'cinco', 'English': 'five'}]
好的,sniffer
成功发现可以在方言中使用skipinitialspaces。
2
是的,DictReader()
可以当作一个可遍历的对象使用,而且可以和filter()
很好地配合使用。
filter()
这个函数会逐行处理每一行数据(每一行是一个字典),如果你给它的函数对这一行返回True
,那么这一行就会被保留下来:
>>> from io import StringIO
>>> import csv
>>> demo = StringIO('''\
... foo,bar,baz
... 42,88,131
... 17,19,23
... ''')
>>> reader = csv.DictReader(demo)
>>> def only_answers(row):
... return '42' in row.values()
...
>>> for row in filter(only_answers, reader):
... print(row)
...
{'baz': '131', 'bar': '88', 'foo': '42'}