在python中依赖于上下文的字符串拆分

时间:2012-01-27 00:09:42

标签: python regex string

道歉,如果这是多余的,但对相互之间的深度搜索显示没有相关内容。

我有一个来自(化学)数据库的字符串,其中分隔符(逗号)偶尔出现在我希望分割的项目中。

是一个示例字符串
s = '2-Methyl-3-phythyl-1,4-naphthochinon,Vitamin, K1,Antihemorrhagic vitamin'

此实例中的正确拆分将产生

splitS = ['2-Methyl-3-phythyl-1,4-naphthochinon', 'Vitamin, K1', 'Antihemorrhagic vitamin']

我相信我能设计出来的最准确的方法就是将逗号分开,逗号旁边没有空格,并且进一步没有被2个数字包围。这将留下诸如'1,4'和'维生素,K1'之类的实例,但将字符串分成正确的3个化学名称。

我尝试过使用RE失败了。我可以发布一些我尝试过的东西,但它几乎没用。非常感谢帮助。

编辑:本来应该包括这个。通过我的一些黑客攻击,以及来自@Borealid的更优雅的解决方案,我已经正确识别了分裂的位置,但获得了可怕的输出,例如

>>> s = '2-Methyl-3-phythyl-1,4-naphthochinon,Vitamin, K1,Antihemorrhagic vitamin'
>>> pat = re.compile("([^\d\s],[^\d\s])|([^\s],[^\d\s])|([^\d\s],[^\s])")
>>> re.split(pat, s)
['2-Methyl-3-phythyl-1,4-naphthochino', 'n,V', None, None, 'itamin, K', None, '1,A', None, 'ntihemorrhagic vitamin']

似乎应该有一种方法可以首先确定要拆分的正确逗号,然后在逗号上拆分,从而避免名称被破坏。

再次感谢

3 个答案:

答案 0 :(得分:5)

您可以使用lookaround获取此行为,以便只匹配符合您解释的逗号:

(?<!\d),(?! )|(?<=\d),(?![\d ])

它似乎对你的示例字符串有正确的行为:

>>> re.split(r'(?<!\d),(?! )|(?<=\d),(?![\d ])', s)
['2-Methyl-3-phythyl-1,4-naphthochinon', 'Vitamin, K1', 'Antihemorrhagic vitamin']

以下是解释:

 (?<!\d),   # match a comma that is not preceeded by a digit...
 (?! )      # ... as long as it is not followed by a space
|           # OR
 (?<=\d),   # match a comma that is preceeded by a digit...
 (?![\d ])  # ... as long as it is not followed by a digit or a space

在写完解释之后,我意识到正则表达式的(?<=\d)部分是不必要的,因为它正如正则表达式的第一部分不匹配所暗示的那样,这意味着你可以将它缩短为以下和得到相同的行为:

(?<!\d),(?! )|,(?![\d ])

答案 1 :(得分:0)

([^\d\s],[^\d\s])|([^\s],[^\d\s])|([^\d\s],[^\s])

之类的东西

逗号((两侧的数字)或(尾侧的数字但不是头侧的数字)或(头侧而不是尾侧的数字))“。

在所有情况下,逗号旁边都没有空格。

\d是“数字”。 \s是“空白”。 []是一个字符类 - [^]是一个倒置的字符类(“匹配一个不在后续内容中的字符”)

不会在字符串的第一个或最后一个位置用逗号分割,但我认为这不会引起关注。

答案 2 :(得分:0)

我有一个解决方案,但有点长。好的,我们走了:

s = '2-Methyl-3-phythyl-1,4-naphthochinon,Vitamin, K1,Antihemorrhagic vitamin'

首先,让我们找到字符串中所有逗号的所有位置(在all_commas中)和所有特殊逗号中的位置(在special_commas中):

all_commas = [match.start() for match in re.finditer(r',', s)]
special_commas = [match.start()+1 for match in re.finditer(r'\d,\d|.,\s', s)]

其次,我们从那些位置(split_commas)中获得了差异。现在,我们有了分裂的位置:

split_commas = set(all_commas) - set(special_commas)

然后,我们将迭代这些拆分位置,并将拆分的字符串保存在splitS

splitS = []
start = -1
for end in sorted(split_commas) + [None]:
    splitS.append(s[start+1:end])
    start = end

最后,这就是我们在splitS中得到的结果:

>>> splitS
['2-Methyl-3-phythyl-1,4-naphthochinon', 'Vitamin, K1', 'Antihemorrhagic vitamin']