【问题标题】:Parsing CSV to list of tuples without using CSV module在不使用 CSV 模块的情况下将 CSV 解析为元组列表
【发布时间】:2023-03-29 03:46:01
【问题描述】:

我目前正在 Python 课程中进行一项作业,其中一个特定部分是要求我导入一个 CSV 文件(数据格式为“文本、数字、数字、...、数字、 number") 不使用 CSV 模块(或任何模块,事实上),并以元组列表的形式返回数据,格式如下:

[(’Text’, [number, number, ..., number, number]),
(’Text’, [number, number, ..., number, number]),
.....]

我想我已经掌握了打开文件并开始逐行读取它的实际过程(参见下面的 sn-p),但我不太确定如何继续解析每一行转换成所需的格式。

def load_data(filename):
    open(filename)
    for line in filename

我尝试过寻求帮助,但我似乎能找到的唯一帮助是只使用 CSV 模块(这并不是特别有用,因为我们不允许导入除数学库之外的任何模块)或有以不同格式输入和/或输出的数据。如果有人能给我一些关于我应该做什么或我可以从哪里开始的指示,那将非常有帮助。谢谢!

编辑:根据@dotancohen 的建议,这里有一些示例数据:

Slow Loris, 21.72, 29.3, 20.08, 29.98, 29.85, 26.22, 29.68
Ocelot, 57.51, 47.59, 55.89, 47.15, 46.71, 51.7, 46.68, 54.54
Tiger, 75.0, 82.43, 112.11, 89.93, 103.19, 80.6, 113.44, 75.55, 102.29, 108.1, 98.84, 101.48, 77.75, 98.57, 70.31, 78.28, 80.18

以下是我目前的潜在解决方案:

def load_data(filename):
    open(filename) as file
    output = []
    for line in filename
        temp_list = line.split(',')
        temp_item = temp_list.pop(0)
        tup = (temp_item, temp_list)
        output.append(tup)
    return output

【问题讨论】:

    标签: python list csv tuples


    【解决方案1】:

    CSV 文件的行通常用逗号或制表符分隔,因此在 naive 情况下,这将为您提供不同的字段:

    for line in filename:
        fields = line.split(',')  # For comma-delimited files
        # - or -
        fields = line.split('\t') # For tab-delimited files
    

    然而,我们很少允许自己如此天真。除其他外,CSV 文件有以下注意事项:

    1. 引用值: 这是 CSV 中的一个合法字段:“我思故我在”。您需要注意不要拆分引号内的逗号。 Newines 也可以出现在引用值中,因此您不能天真可靠地使用 for line in filename
    2. 引用值中的转义引号:这是 CSV 中的一个合法字段:“她说\”我这么认为\“”。这意味着您用于匹配每个字符的内引用外引用状态的状态机也需要一个回溯机制。

    因此,要可靠地解析 CSV 文件,您需要一个状态机来跨行保存文件中的状态。在此过程中会出现可怕的惊喜,例如在 Python 2 中处理 Unicode CSV 文件(提示:如果您有非 ASCII 文本,请使用 Python 3)。还有一些小惊喜,例如一些应用程序在逗号分隔符后放置一个空格,或者没有在行尾为空白字段添加逗号。

    因此,如果您要接受 CSV 文件作为用户的输入,请使用 CSV 模块。但是,如果您可以控制输入(即从另一个脚本生成它),那么您可以使用幼稚的line.split('\t') 方法。

    根据 OP 发布的示例数据,我们看到他不必担心引用字段,但他的 CSV 源实际上是在逗号分隔符后添加了错误的空格。因此,这是特定于 OP 情况的代码:

    for line in filename:
        fields = line.split(',')
        fields = [x.strip() for x in fields] # Remove whitespace
    

    【讨论】:

    • 对,所以我将使用 line.split(',') 因为我的文件完全是逗号分隔的。虽然我无法控制输入,但我们已经获得了将测试程序的两个 CSV 文件,它们都具有相同的一致格式,没有引用值、转义引号或非 unicode 字符(尽管我们正在使用蟒蛇3)。我应该将文本拆分为一个单独的变量,然后将文本作为元组重新加入数字吗?那应该给出我正在寻找的输出,对吧?
    • @RandosaurusRex - 这看起来是一个很好的工作方法。您可以在没有进一步帮助的情况下完成它,但是如果您尝试该设计并且遇到问题,请回来寻求详细的帮助。我怀疑从这里开始你会没事的,但如果你确实在这和结束之间遇到了一个绊脚石,我不会感到羞耻。
    • @RandosaurusRex:我希望在给出是或否之前先查看示例文件,您能否在问题中添加一些示例行?谢谢。
    • @RandosaurusRex:查看我编辑的答案,该答案针对您的数据。
    • @dotancohen 等等,这不会删除“Slow Loris”中的空格吗?嗯。
    【解决方案2】:

    要查看的一个关键概念是split()

    根据逗号拆分 CSV 似乎是难题的重要组成部分,您不同意吗?

    【讨论】:

    • 所以我应该使用类似于 line.split(',') 的东西?如果我这样做,我是否应该将列表分成两个子列表,一个带有文本,另一个带有数字,然后以某种方式将它们链接为单个列表项?
    【解决方案3】:

    这是CSV 文件中的data

    text1   1   2   3   4   5
    text2   6   7   8   9   10
    text3   11  12  13  14  15
    

    您可以使用setdefaultzip 在Python2 中实现您需要的输出

    d = {}
    with open('your_file.csv', 'rb') as f:
        for line in f:
            line = line.split()
            for i in line[1:]:
                key = (line[0])
                d.setdefault(key, []).append(int(i))
    
    x = sorted(d.keys())
    y = sorted(d.values())
    lst = zip(x,y)
    print (lst)
    

    输出:

    [('text1', [1, 2, 3, 4, 5]), ('text2', [6, 7, 8, 9, 10]), ('text3', [11, 12, 13, 14, 15])]
    

    Python3 中,您必须将这一行 lst = zip(x,y) 替换为 lst = list(zip(x,y))

    【讨论】:

      【解决方案4】:

      mycsv 文件内容:(data.csv)

      "New Zealand,46 - 15,Argentina ,01/06/1987,31"
      "France,70 - 12,Zimbabwe ,02/06/1987,58"
      "Wales,40 - 9,Canada ,03/06/1987,31"
      "England,34 - 6,USA ,03/06/1987,28"
      "New Zealand,49 - 6,Wales ,14/06/1987,43"
      "New Zealand,70 - 6,Italy ,22/05/1987,64"
      "Canada,37 - 4,Tonga ,24/05/1987,33"
      "New Zealand,74 - 13,FIJI ,27/05/1987,61"
      "France,55 - 12,Romania ,28/05/1987,43"
      "England,60 - 7,Japan ,30/05/1987,53"
      

      无需 csv 模块即可读取 csv 并将每一行存储到列表中的代码:

      fo = open("data.csv", 'r')
      data = fo.read()
      fo.close()   
      
      games=[]
      data = data.splitlines()
      for line in data:
          games.append(line.split(","))
          
      print(games)
      

      【讨论】:

        猜你喜欢
        • 2021-03-22
        • 1970-01-01
        • 2020-09-27
        • 2018-12-11
        • 2011-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多