当前位置: 首页 > 知识库问答 >
问题:

如果分隔符被括号包围,如何防止Python字符串被拆分()

赵嘉悦
2023-03-14

我正在编写一段代码,循环遍历一个txt文件,并创建一个包含各行的列表。我需要每行的特定内容,其中逗号用作分隔符。然而,当其中一个列表项中有一个逗号时,我遇到了一个问题。列表理解行将单个项目分为两个项目。作者一词用括号括起来。我可以要一份括号里的清单吗?

    inventory = open("inventory.txt").readlines()
    seperated_inventory = [x.split(",") for x in inventory]
    isbn_list = [item[0] for item in seperated_inventory]
    author_list = [item[1] for item in seperated_inventory]
    title_list = [item[2] for item in seperated_inventory]
    category_list = [item[3] for item in seperated_inventory]
    active_list = [item[4] for item in seperated_inventory]

两位作者的连线示例

0520085477,[Richard L.Abel],[Philip Simon Coleman Lewis],社会律师,[Law],False


共有1个答案

尹雅健
2023-03-14
匿名用户

我认为,当您有子列表可以包含要拆分的字符时,使用单个字符拆分并不是一个好策略。

有三种主要方法可以实现这一点(我已经想到了)。嗯,有两种方法和一种选择:

这相当脆弱、冗长,而且不如第二种方法。我把它放在第一位是因为它直接回答了问题,而不是因为它是你应该做的:

line="0520085477,['Richard L. Abel', 'Philip Simon Coleman Lewis'],Lawyers in Society,['Law’],False"

# Index of the left hand side of any found sub-arrays.
left = 0
# Iterator position, also used as the index of the right hand side of any found sub-arrays.
right = 0
array = line.split(',')
while right < len(array):
    if array[right].startswith('['):
        array[right] = array[right][1:] # Remove the bracket
        left = right

    if array[right].endswith(']'):
        array[right] = array[right][:-1] # Remove the bracket
        # Pull the stuff between brackets out into a sub-array, and then
        # replace that segment of the original array with a single element
        # which is the sub-array.
        array[left:right+1] = [array[left:right+1]]
        # Preserve the "leading search position", since we just changed
        # the size of the array.
        right = left
    right += 1

print(array)

如您所见,该代码远不如理解清晰。它也很复杂;它可能有我没有测试的错误和边缘案例。

这只适用于单层嵌套子阵列。

尽管xkcd对regex说了些什么,但在这种情况下,它是提取子数组的更清晰、更简单的解决方案。有关如何使用regex的更多信息,请参阅re模块的留档。在线regex测试器也很容易获得,并且在调试正则表达式时非常有帮助。

import re

line="0520085477,['Richard L. Abel', 'Philip Simon Coleman Lewis'],Lawyers in Society,['Law’],False"

r = re.compile(r'(?:\[(?P<nested>.*?)\]|(?P<flat>[^,]+?)),')
array = []
# For each matched part of the line, figure out if we matched a
# sub-array (in which case, split it on comma and add the resulting
# array to the final list) or a normal item (just add it to the final
# list).

# We append a comma to the string we search so our regex always matches
# the last element.
for match in r.finditer(line + ","):
    if match.group('nested'): # It's a sub-array
        array.append(match.group('nested').split(","))
    else: # It's a normal top-level element
        array.append(match.group('flat'))

print(array)

正则表达式粗略地说:

  1. 启动一个非捕获组(?:),该组包装这两个子模式。就像括号强制数学公式中的运算顺序一样,这明确表明此正则表达式末尾的尾随逗号不是两个捕获组的一部分。严格来说,这不是必要的,但会让事情变得更清楚
  2. 匹配两组中的一组。第一组是一对方括号之间的一些字符,忽略逗号和拆分。匹配应该缓慢地进行(看到右括号时立即停止;这是?),匹配中的任何内容都应该对名为“nested”的正则表达式API可用。名称完全可选;也可以使用match对象上的数组索引,但这对于代码读取器更为明确
  3. 第二组可以匹配的字符是一些不包含逗号的字符([^,])。根据正则表达式引擎的迫切性,您可能会将其替换为“任意字符”,并信任外部非捕获字符之外的逗号: 组可以防止这些匹配项跑掉,但对读者来说,说“不是逗号”更明确。与此组匹配的任何内容都应以“flat”的名称存储
  4. 最后,在出现这两种模式后查找逗号。由于数组中的最后一个元素后面没有逗号,所以我只是用一行加一个额外的逗号来拼凑和匹配,而不是进一步使正则表达式复杂化

一旦理解了正则表达式,剩下的就很简单了:遍历每个匹配项,看看它是“平面”还是“嵌套”,如果是嵌套的,则根据逗号拆分它并将其作为子数组添加到结果中。

这只适用于单个级别的嵌套子数组,如果逗号彼此相邻,或者子数组不是“闭合”(基本上是输入格式错误)的话,这将破坏/发生意外的事情,这让我想到。

这两种解析器都容易出错。数组中的元素可能包含特殊字符(例如,如果像这样的标题的名称中有一个方括号怎么办?),多个逗号可能出现在“空”字段周围,您可能需要多层次的嵌套子数组(您可以使前两个选项中的任何一个递归,但代码只会变得更难阅读),或者,也许最常见的是,您可能会收到稍微损坏/不符合您期望的输入,并且无论如何都必须解析它。

处理所有这些问题可以用更多的代码来完成,但这些代码通常会降低解析系统的可靠性,而不是更高。

相反,考虑将您的数据交换格式切换为类似JSON的格式。您提供的行已经几乎是有效的JSON,因此您可以直接使用jsonPython模块,让事情“正常工作”,而无需编写一行解析代码。结构化数据解析还有许多其他选项,包括YAML和TOML。您在该领域选择的任何东西都可能比手动滚动解析逻辑更健壮。

当然,如果这是为了娱乐/教育,并且您想从头开始制作一些东西,请编写代码!解析器是一个很好的教育项目,因为有很多角落案例,但每个角落案例往往是离散的/与其他奇怪案例的交互很小。

 类似资料:
  • 在逗号处划分字符串的最佳方法是什么,这样每个单词都可以成为ArrayList的一个元素? 例如:

  • 问题内容: 欲分割为4的阵列,以利用 这是我的代码: 但是,结果标记是一个空数组:[],而不是 我想要的4数组。 我已经测试过更改一点: 这次的结果标记为。这与我想要的接近,但是我真的不想在拆分之前添加此“ 1”。 问题基本上是,如果它仅包含空元素,它将返回一个空数组。 您能帮助解决问题吗? 问题答案: 您需要使用带有limit参数的重载方法。 从文档(重点是我的): limit参数控制应用图案的

  • 我有输入字符串'~~'作为分隔符。 例如:字符串s=“1~~vijay~~25~~pune”;当我在Java中用'~\\~'拆分它时,它工作得很好。 还有其他人面临同样的问题吗?请就这个问题发表评论。

  • 我有一个长字符串,只要逗号不在方括号或圆括号内,我想通过用逗号将其拆分来将其设置为数组。我已经尝试了一些变化,但没有得到我想要的。。。 例1: 例2:

  • 因此,这将匹配以下逗号分隔的字符串: 然后,我可以使用对非字符执行相同的操作,它将匹配: 我想创建一个regex来匹配包含特殊字符、连字符和下划线的字符串,例如。 下面是另一个例子: 这是无效的,因为有两个逗号;必须只有一个。

  • 问题内容: 我需要在数据库中填充纬度和经度列,但是原始信息存储为单个字符串 例如。 我猜想TRIM命令在这里很有用,但是我不知道如何告诉它每半个部分都精确地停在逗号上。 我希望能够提出一个简单的UPDATE查询,如下所示: 但是显然在LTRIM和RTRIM部分中需要做一些额外的工作,因此我只选择数据,但不包括UDFChar1中的逗号。 关于如何实现这一目标的任何想法? 问题答案: 请试试: 和 样