使用特定条件连接列表中的项目

2024-10-01 17:32:13 发布

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

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

//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"', '"<color=asdf>d1', 'd2', 'd3<br>d4"d5"', 'd6.</color>, 0, 1, false"',列表长度为14

当我想要的时候:

['1', 'false', 'false', '0', '"0"', '"0"', '"0"', '"<color=asdf>d1, d2, d3<br>d4"d5", d6.</color>, 0, 1, false"',列表长度为11,因此列表的长度对应于描述行f1, f2... f11

在我看来,引号(“”中的逗号通过拆分所有内容导致了.split(',')方法的这个问题

我一直试图找到一种方法,我可以合并'正确'的项目在一起,但没有任何效果。有人能帮我解决这个问题吗


Tags: 文件brfalse列表结构colorf2f1
1条回答
网友
1楼 · 发布于 2024-10-01 17:32:13

对于这个答案,我将假设颜色标记对应于列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]用于切掉最后一个字符。将初始regex match语句与上面的表达式结合起来,并使用它们替换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(','))

我希望这能帮助你解决你的问题。如果没有,请随时询问

相关问题 更多 >

    热门问题