0

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

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

当预期结果是:

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

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

['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
4

2 回答 2

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"', '"Intro to 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
于 2020-05-04T18:29:34.577 回答
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 解析器、递归下降、移位归约解析器。

于 2020-05-04T18:48:30.170 回答