Python 最大化正则表达式中的子字符串匹配

Python 最大化正则表达式中的子字符串匹配,python,regex,Python,Regex,我想从单词中提取元素符号(如果存在)。为此,我准备了一个正则表达式匹配模式,它包含元素周期表中所有元素的符号 H|He|Li|Be|B|C|N|O|F|Ne|Na|Mg|Al|Si|P|S|Cl|Ar|K|Ca|Sc|Ti|V|Cr|Mn|Fe|Co|Ni|Cu|Zn|Ga|Ge|As|Se|Br|Kr|Rb|Sr|Y|Zr|Nb|Mo|Tc|Ru|Rh|Pd|Ag|Cd|In|Sn|Sb|Te|I|Xe|Cs|Ba|La|Ce|Pr|Nd|Pm|Sm|Eu|Gd|Tb|Dy|Ho|Er|Tm|

我想从单词中提取元素符号(如果存在)。为此,我准备了一个正则表达式匹配模式,它包含元素周期表中所有元素的符号

H|He|Li|Be|B|C|N|O|F|Ne|Na|Mg|Al|Si|P|S|Cl|Ar|K|Ca|Sc|Ti|V|Cr|Mn|Fe|Co|Ni|Cu|Zn|Ga|Ge|As|Se|Br|Kr|Rb|Sr|Y|Zr|Nb|Mo|Tc|Ru|Rh|Pd|Ag|Cd|In|Sn|Sb|Te|I|Xe|Cs|Ba|La|Ce|Pr|Nd|Pm|Sm|Eu|Gd|Tb|Dy|Ho|Er|Tm|Yb|Lu|Hf|Ta|W|Re|Os|Ir|Pt|Au|Hg|Tl|Pb|Bi|Po|At|Rn|Fr|Ra|Ac|Th|Pa|U|Np|Pu|Am|Cm|Bk|Cf|Es|Fm|Md|No|Lr|Rf|Db|Sg|Bh|Hs|Mt
现在,对于给定的单词,我想使用上面的正则表达式模式从中提取元素。我现在面临的问题是

CuIn2Se
我能提取

C,In,S
作为元素。这是一个错误的提取,因为我需要

Cu, In, Se
从正则表达式中,我得到了“C,In,S”,我相信这是因为匹配模式在“Cu”之前看到了“C”,在“Se”之前看到了“S”(例如,当前的匹配模式是like)


为了解决这个问题,我想,我必须通过搜索模式中的所有单词来确保正则表达式匹配单词中最大数量的字符

正确的方法是按长度的降序排列所有元素

>>> import re
>>> pat = re.compile('Cu|In|Se|C|S')
>>> s = 'CuIn2Se'
>>> pat.findall(s)
['Cu', 'In', 'Se']
这一点在报告中有明确的解释

小纸条

鉴于您的输入字符串非常长,我编写了一个小脚本,使其按长度的降序排序。这可能对你有帮助

'|'.join(sorted(s.split('|'),key = len,reverse = True))

我会采取不同的方法,只是为了与众不同。与其在一个大的正则表达式中列出所有的化合物,不如把它们做成一个集合,抓取所有可能是化合物的东西,然后在事实发生后进行过滤

import re

molecule = "CuIn2Se"

compounds = re.findall("[A-Z][a-z]?", molecule)

all_compounds = set(("H, He, Li, Be, B, C, N, O, F, Ne, Na, Mg, "
                     "Al, Si, P, S, Cl, Ar, K, Ca, Sc, Ti, V, "
                     "Cr, Mn, Fe, Co, Ni, Cu, Zn, Ga, Ge, As, Se, "
                     "Br, Kr, Rb, Sr, Y, Zr, Nb, Mo, Tc, Ru, Rh, Pd, "
                     "Ag, Cd, In, Sn, Sb, Te, I, Xe, Cs, Ba, La, Ce, "
                     "Pr, Nd, Pm, Sm, Eu, Gd, Tb, Dy, Ho, Er, Tm, "
                     "Yb, Lu, Hf, Ta, W, Re, Os, Ir, Pt, Au, Hg, Tl, "
                     "Pb, Bi, Po, At, Rn, Fr, Ra, Ac, Th, Pa, U, Np, "
                     "Pu, Am, Cm, Bk, Cf, Es, Fm, Md, No, Lr, Rf, Db, "
                     "Sg, Bh, Hs, Mt").split(", "))

actual_compounds = filter(lambda ch: ch in all_compounds, compounds)
如果要搜索大量字符串,这应该会更快,因为测试集成员资格比正则表达式解析快得多。如果您只有几个,那么构建集合的成本可能会超过解析字符串的速度。黄金法则是评测代码,记住过早优化是万恶之源

您也可以使用模块的命名列表:

>>> import regex
>>> s='H|He|Li|Be|B|C|N|O|F|Ne|Na|Mg|Al|Si|P|S|Cl|Ar|K|Ca|Sc|Ti|V|Cr|Mn|Fe|Co|Ni|Cu|Zn|Ga|Ge|As|Se|Br|Kr|Rb|Sr|Y|Zr|Nb|Mo|Tc|Ru|Rh|Pd|Ag|Cd|In|Sn|Sb|Te|I|Xe|Cs|Ba|La|Ce|Pr|Nd|Pm|Sm|Eu|Gd|Tb|Dy|Ho|Er|Tm|Yb|Lu|Hf|Ta|W|Re|Os|Ir|Pt|Au|Hg|Tl|Pb|Bi|Po|At|Rn|Fr|Ra|Ac|Th|Pa|U|Np|Pu|Am|Cm|Bk|Cf|Es|Fm|Md|No|Lr|Rf|Db|Sg|Bh|Hs|Mt'
>>> p=regex.compile(r"\L<options>", options=s.split('|'))
>>> p.findall('CuIn2Se')
['Cu', 'In', 'Se']
导入正则表达式 >>>“H”s'124岁,H'124岁,H'124岁,H'124岁,H'124岁,H'124岁,H'124岁,H'124岁,H'124岁,H'124岁,他认为,他是该该方的死亡,他认为该方的死亡,他是该方的本方的死亡死亡死亡死亡,该方的死亡,该方的死亡死亡,该方的死亡,该方的死亡,本本本本方的死亡死亡,本方的其他其他其他其他其他其他其他本方为为为本本本本方的死亡,本本本本方的死亡,本方,本本本方为为为为为为为本方,本方,本方,本方,本方,本方,本方,本方,本方为为为为为为本方,本方,本方,本方,本方,本方,本方,本方,本方,本方,本方为为为为为为本方,本方,本方,本方,《1240》YよYよYよYよY YよYよY YよYよYよY Y|Y Y|Y Y Y|Y Y Y Y|Y|Y Y|Y Y|非非非非托托托托卡维维维维非非非非非非托托托托托托非非非非非非非非非非非非托托托托托托托托托托托托托托托托非非非非非非非非非非非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托非托奥斯|伊尔|帕特| Au | Hg | Tl | Pb | Bi | Po | At | Rn | Fr | Ra | Ac | Th | Pa | U | Np Pu Am | Cm | Bk | Cf | Es | Fm Md No | Lr | Rf Db | Bh | >>>p=regex.compile(r“\L”,options=s.split(“|”)) >>>p.findall(“CuIn2Se”) ['Cu','In','Se'] 另一种简单的方法

x="CuIn2Se"
print re.findall(r"(?:C|In|S|Cu|Se)(?=[A-Z0-9]|$|\s)",x)

感谢您的建议,我完全可以做到这一点(根据字符数对正则表达式模式进行排序)。我想知道是否有其他方法可以在不改变正则表达式模式中单词顺序的情况下使用。@Nakamura添加了一个脚本来帮助您对输入进行排序。你可以把它放在一个黑盒子里!非常感谢,是的,我现在继续在正则表达式模式中对我的单词进行排序,并在正则表达式匹配期间使用修改后的模式。我在文档中找不到这个。你能说出它在那个页面上的位置吗?我现在相信它真的不在你链接的那个页面上,我建议你改为链接到那个页面,它确实在说。这很好!我正在检查
regex
模块是否支持
\G
(它确实支持),但命名列表非常适合此工作。
x="CuIn2Se"
print re.findall(r"(?:C|In|S|Cu|Se)(?=[A-Z0-9]|$|\s)",x)