如何在不使用CSV导入的情况下用python编写自定义CSV读取器?

2024-05-19 15:40:32 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

当预期结果为:

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

我注意到问题与引号“&;”有关,但仍然没有找到正确的答案,对line变量使用replace(“,”)来删除双引号并不能修复它,因为它返回为:

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

删除某些单词的最后一个引号,例如Zelle,而不是Zelle'

下面我将提供一个到练习、问题和我当前脚本的链接。非常感谢您的任何解释或帮助

链接: http://www.pyschools.com/quiz/view_question/s13-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

Tags: 文件csvto脚本网站html记录line
2条回答

和往常一样,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解析器

我在找你要读的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

相关问题 更多 >