Python正则表达式用于解析成2D数组

4

我有一个字符串需要解析成二维数组:

 str = "'813702104[813702106]','813702141[813702143]','813702172[813702174]'"

数组等效物将是:

arr[0][0] = 813702104
arr[0][1] = 813702106
arr[1][0] = 813702141
arr[1][1] = 813702143
#... etc ...

我尝试使用正则表达式来实现这个。上面的字符串被嵌在HTML页面中,但我可以确定它是页面上该模式中唯一的字符串。我不确定这是否是最好的方法,但这是我目前所拥有的全部。

imgRegex = re.compile(r"(?:'(?P<main>\d+)\[(?P<thumb>\d+)\]',?)+")

如果我运行imgRegex.match(str).groups(),我只能得到一个结果(第一对)。如何才能获得多个匹配或2D匹配对象(如果这样的东西存在的话)?请注意:与它看起来的方式相反,这不是作业。注2:真正的字符串嵌入在一个大的HTML文件中,因此分割似乎不是一个选项。我仍然在为此问题寻找答案,所以我想我最好编辑一下,以显示为什么我不改变接受的答案。尽管在这个测试字符串上更有效率,但拆分不会从整个HTML文件中提取部分。我可以结合使用正则表达式和拆分,但那似乎很愚蠢。如果您有更好的方法来查找一堆HTML中的部分(模式\d+\[\d+\]在源中是唯一的),我将很高兴更改接受的答案。其他任何事情都是学术性的。

我添加了我认为arr[1][0]和arr[1][1]应该是什么样子的,因为不是很清楚。但我不懂Python,所以无法帮助你回答问题。 - Kip
是的,我最初也有[2][*],但不确定是否会使帖子混乱,但我理解你的观点。感谢您的编辑。 - Oli
你的意思是: str = "'813702104[813702106]','813702141[813702143]','813702172[813702174]'" - Benedikt Waldvogel
5个回答

6
我建议您使用findallfinditer而不是match。Oli编辑后说:findall非常好用,但我需要简化正则表达式:
r"'(?P<main>\d+)\[(?P<thumb>\d+)\]',?"

哇!findall使用稍微简化的正则表达式就可以工作了。我会修改您的答案以展示有效的方法。谢谢! - Oli

3

我认为在这个任务中不需要使用正则表达式。Python列表推导式非常强大。

In [27]: s = "'813702104[813702106]','813702141[813702143]','813702172[813702174]'"

In [28]: d=[[int(each1.strip(']\'')) for each1 in each.split('[')] for each in s.split(',')]

In [29]: d[0][1]
Out[29]: 813702106

In [30]: d[1][0]
Out[30]: 813702141

In [31]: d
Out[31]: [[813702104, 813702106], [813702141, 813702143], [813702172, 813702174]]

我解释了为什么我认为正则表达式是唯一的方法:现实生活中的字符串不是一个纯粹的小数组。它被埋在一个100k的HTML文件中。我可以通过正则表达式提取,然后再分割...但这似乎有点傻,不是吗? - Oli

1

稍微修改一下你的正则表达式,

>>> str = "'813702104[813702106]','813702141[813702143]','813702172[813702174]"
>>> imgRegex = re.compile(r"'(?P<main>\d+)\[(?P<thumb>\d+)\]',?")
>>> print imgRegex.findall(str)
[('813702104', '813702106'), ('813702141', '813702143')]

什么是“二维数组” - 在Python中,它是“由2个元组组成的列表”。


1

我已经有了一些在你的数据集上似乎有效的东西:

In [19]: str = "'813702104[813702106]','813702141[813702143]','813702172[813702174]'"
In [20]: ptr = re.compile( r"'(?P<one>\d+)\[(?P<two>\d+)\]'" )
In [21]: ptr.findall( str )
Out [23]:
[('813702104', '813702106'),
 ('813702141', '813702143'),
 ('813702172', '813702174')]

1

或者,您可以使用Python的[语句 for item in list]语法来构建列表。对于小数据集,您应该发现这比正则表达式要快得多。对于较大的数据集,差异不会太大(它只需要一次加载正则表达式引擎,无论大小),但列表生成器始终应该更快。

首先通过逗号拆分字符串:

>>> str = "'813702104[813702106]','813702141[813702143]','813702172[813702174]'"
>>> arr = [pair for pair in str.split(",")]
>>> arr
["'813702104[813702106]'", "'813702141[813702143]'", "'813702172[813702174]'"]

现在,这返回与str.split(",")相同的东西,所以并不是很有用,但您应该能够看到listmaker是如何工作的——它会遍历列表,将每个值分配给item,执行语句,并将结果值附加到新建的列表中。

为了完成一些有用的事情,我们需要放入一个真正的语句,以便我们获得每对中括号的切片,从而删除单引号和闭合中括号,然后方便地在该位置进一步拆分开口中括号:

>>> arr = [pair[1:-2].split("[") for pair in str.split(",")]
>>> arr
>>> [['813702104', '813702106'], ['813702141', '813702143'], ['813702172', '813702174']]

这将返回一个二维数组,就像您所描述的那样,但其中的项都是字符串而不是整数。如果您只是将它们用作字符串,那就足够了。如果您需要它们成为实际的整数,您只需使用“内部”列表生成器作为“外部”列表生成器的语句:

>>> arr = [[int(x) for x in pair[1:-2].split("[")] for pair in str.split(",")]
>>> arr
>>> [[813702104, 813702106], [813702141, 813702143], [813702172, 813702174]]

这将返回一个二维整数数组,表示您提供的字符串中的数字,而无需加载正则表达式引擎。


Ben,我已经编辑了这篇文章,强调在实际应用中,该字符串来自一个大型HTML文件,因此普通的分割并不是一个直接的选择。 - Oli
啊,是的。如果你需要使用正则表达式从HTML中提取它,那么你也可以继续使用它们。:-D - Ben Blank

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接