【问题标题】:Joining items in list with specific conditions Python使用特定条件Python加入列表中的项目
【发布时间】:2020-09-19 07:00:02
【问题描述】:

我目前正在处理 csv 文件中的 100,000 多行,其结构如下:

//f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11
1,false,false,0,"0","0","0","<color=asdf>d1, d2, d3<br>d4"d5", d6.</color>, 0, 1, false"
2,true,false,0,"0","0","0","<color=qwer>d1, "d2, d3"<br> d3<br>d4"d5" d6.</color>, 0, 1, false"
...

最上面一行是文件的结构。

我一直在尝试循环遍历每一行代码,为每个值(f1,f2...)分配相应的值,并使用生成器修改文本,但我面临拆分的问题代码正确。

如果我只是使用line.split(',') 拆分行,我将拥有:

['1', 'false', 'false', '0', '"0"', '"0"', '"0"', '"&lt;color=asdf&gt;d1', 'd2', 'd3&lt;br&gt;d4"d5"', 'd6.&lt;/color&gt;, 0, 1, false"',列表长度为 14

当我想要的时候:

['1', 'false', 'false', '0', '"0"', '"0"', '"0"', '"&lt;color=asdf&gt;d1, d2, d3&lt;br&gt;d4"d5", d6.&lt;/color&gt;, 0, 1, false"',列表长度为11,使得列表长度对应描述行f1, f2... f11

在我看来,引号 ("") 中的逗号通过拆分所有内容导致 .split(',') 方法出现此问题。

我一直在尝试找到一种可以将“正确”项目合并在一起的方法,但无济于事。谁能帮我解决这个问题?

【问题讨论】:

    标签: python string list loops


    【解决方案1】:

    对于这个答案,我将假设颜色标签对应于 f8 列,并且以下整数和布尔值分别对应于 f9、f10 和 f11 列。这与布尔列末尾的引号位置不匹配,但这是我能想到的最明显的方法,以确保示例行确实分别为 14 列和 11 列长。如果这不是 csv 文件的预期结构,请澄清,我很乐意相应地编辑答案。

    您可以使用标准库模块csv 中的解析器来为您解析文件,而不是自己组合字符串。例如,一个名为datafile.csv 的文件可以显示为:

    import csv
    with open("datafile.csv", 'r') as csvfile:
        csvreader = csv.reader(csvfile)
        for row in csvreader:
            print(row)
    

    也就是说,在您提供的行上进行测试会得到

    ['1', 'false', 'false', '0', '0', '0', '0', '<color=asdf>d1, d2, d3<br>d4d5"', ' d6.</color>', ' 0', ' 1', ' false"']
    ['2', 'true', 'false', '0', '0', '0', '0', '<color=qwer>d1, d2', ' d3"<br> d3<br>d4"d5" d6.</color>', ' 0', ' 1', ' false"']
    

    与您要查找的结果不匹配。这是因为我认为应该是一列的颜色标签包含未转义的引号。因此,解析器无法判断该列应该在哪里结束。如果您控制生成 csv 文件的代码,最好在此处进行更改,但如果您无法更改数据文件的生成,则也必须解决此问题。

    如果列 f8 始终对应于一个颜色标签,您可以使用此知识将其拆分,然后用逗号拆分该行的其余部分。为此,我们可以使用regular expressions module。我们不使用line.split(','),而是将行分成3 部分:颜色标签之前的部分、标签本身和之后的部分。这可以通过

    result = re.match(r"(.*),(\"\<color.*\</color\>),(.*)", line)
    

    result 将包含一个Match 对象,该对象将具有与括号括起来的位置相对应的“捕获组”。我们可以通过调用Match.group 方法从对象中提取这些捕获组,并将组的位置作为参数。第一组和第三组可以安全地用逗号分隔,因为我们已经观察到它们只包含内部没有逗号的简单数据,而包含颜色标签的第二组不需要拆分,因为它包含单个列。因此,我们获得了最终列表

    result.group(1).split(',') + [result.group(2)] + result.group(3).split(',')
    

    如果引号的位置与提供的数据中一样,但您希望将其更改为接近颜色标签,这可以通过从第三个捕获组的末尾删除引号并将其添加到第二。这样,上面的表达式就变成了

    result.group(1).split(',') + [result.group(2) + '"'] + result.group(3)[:-1].split(',')
    

    其中[:-1] 用于切掉最后一个字符。将初始正则表达式匹配语句与上面的表达式组合并使用它们替换 line.split(',') 应该会产生所需的结果。使用这种方法,显示 csv 文件的所有行将如下所示:

    import re
    with open("testing.csv", 'r') as csvfile:
        for line in csvfile.readlines():
            print(line)
            result = re.match(r"(.*),(\"\<color.*\</color\>),(.*)", line)
            print(result.group(1).split(',') + [result.group(2) + '"'] + result.group(3)[:-1].split(','))
    

    我希望这可以帮助您解决问题。如果没有,请随时询问。

    【讨论】:

    • 非常感谢您提供的信息!不幸的是,在我看来,有 100,000 多行代码,在“分隔逗号”之间有更多带有逗号和引号的模式。有些行甚至没有颜色标签本身,所以我认为你的解决方案将是解决这个问题的非常有见地的方法之一。
    • 啊,真不幸。除非有办法确保正确转义内引号,否则自动解析这些变化的数据并不容易。无论如何,祝你好运,我希望你能找到你正在寻找的解决方案。
    猜你喜欢
    • 2013-02-28
    • 2015-10-08
    • 1970-01-01
    • 2021-07-21
    • 2017-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多