在DictReader上使用Filter()

1 投票
2 回答
4630 浏览
提问于 2025-04-18 02:41

我刚开始学习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'}

撰写回答