如何在python中编写一个自定义的CSV阅读器,而不使用csv导入?

问题描述 投票:0回答:1

我试图解决一个问题,pyschools网站要求编写一个脚本,读取一个以逗号", "作为分隔符的CSV文件并返回一个记录列表。当在他们的网站上运行我的脚本时,使用测试用例:csvReader('books.csv')[0]返回不正确的结果,从而返回:

['"Pete,Zelle","Intro to HTML, CSS",2011']

当预期的结果是:

['Pete,Zelle', 'Intro to HTML, CSS', '2011']

我注意到这个问题与引号"& '有关,但仍然没有找到正确的答案,使用replace('"','')来删除行变量中的双引号并不能解决这个问题,因为它返回的是:

['Pete,Zelle,Intro to HTML, CSS,2011']

其中它删除了一些单词的最后一个引号,例如Zelle,而不是Zelle',。

下面将提供练习、问题和我当前脚本的链接。任何解释或帮助都是非常感激的。

链接。http:/www.pyschools.comquizview_questions13-q8

问题:写一个函数来读取一个以','作为分隔符的CSV文件,并返回一个记录列表.该函数必须能够忽略双引号'"内的','。

脚本。

def csvReader(filename):
    records = []
    for line in open(filename):
        line = line.rstrip()  # strip '\n'
        if line=='","':
           continue           # ignore empty line

        records.append([line.replace('"','')])


    return records
python list python-2.7 csv file-io
1个回答
0
投票

我是在你试图读取的CSV文件之后。听起来你需要将字段分开,同时忽略引号之间的任何定界符。

在这种情况下,我建议使用CSV库并设置引号字符。

import csv
record = '"Pete,Zelle","Intro to HTML, CSS",2011'
newStr = [ '"{}"'.format(x) for x in list(csv.reader([record], delimiter=',', quotechar='"'))[0] ]
print(newStr)

将返回['"Pete,Zelle"', '"HTML, CSS介绍"', '"2011"']。

在你的功能中,你可以加入以下内容

import csv
def csvReader(filename):
    records = []
    for line in open(filename):
        line = line.rstrip()  # strip '\n'
        if line=='","':
           continue           # ignore empty line
        newLine = [ '"{}"'.format(x) for x in list(csv.reader([line], delimiter=',', quotechar='"'))[0] ]
        records.append(newLine)

    return records

0
投票

电池照例是包含在python中的。这里使用的是标准的lib csv模块。

import csv
with open(path, "r") as f:
    csv_reader = csv.reader(f, delimiter=",")
    for row_number, row in enumerate(csv_reader):
        print(f"{row_number} => {row}")

如果stdlib因为一些奇怪的原因不能使用 你需要用 "分隔符","分隔符 "和 "单元格值 "来标记每一行。同样,这在stdlib中也是很简单的。import re). 让我们假设你没有电池,只需要 plain python.

你需要意识到,如何处理每一行的每个字符取决于 "上下文",而这个上下文是由前面所有字符建立起来的。这里建议使用堆栈。根据当前的上下文(堆栈的顶部)和当前的字符,你可以从堆栈中推送和弹出状态(也就是上下文)。现在,给定一个上下文,你可以根据上下文处理每个字符。

class State: 
    IN_NON_DELIMITED_CELL = 1 
    IN_DELIMITED_CELL = 2 

def get_cell_values(line, quotechar='"', separator=','): 
    stack = [] 
    stack.append(State.IN_NON_DELIMITED_CELL) 
    cell_values = [""] 
    for character in line: 
        current_state = stack[-1] 
        if current_state == State.IN_NON_DELIMITED_CELL: 
            if character == quotechar: 
                stack.append(State.IN_DELIMITED_CELL) 
            elif character == separator: 
                cell_values.append("") 
            else: 
                cell_values[-1] += character 

        if current_state == State.IN_DELIMITED_CELL: 
            if character == quotechar: 
                stack.pop() 
            else: 
                cell_values[-1] += character 
    return cell_values 

with open(path, "r") as f:
    for line in f:
        cell_values = tokenize(line, quotechar='"', delimiter=',')
        print(cell_values)

这是一个很好的出发点:

print(get_cell_values('"this","is",an,example,of,"doing things, the hard way?"'))
# prints:
['this', 'is', 'an', 'example', 'of', 'doing things, the hard way?']

要想更进一步,可以看看这些主题: 符号化字符串,LL+LR解析器,递归后裔,shift-reduce解析器。

© www.soinside.com 2019 - 2024. All rights reserved.