首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >根据关键字将字符串分解为列表元素

根据关键字将字符串分解为列表元素
EN

Stack Overflow用户
提问于 2012-03-20 15:27:50
回答 3查看 3K关注 0票数 7

我正在尝试创建一个函数(在Python中),该函数接受其输入(一个化学公式)并拆分成一个列表。例如,如果输入是"HC2H3O2",它将转换为:

代码语言:javascript
复制
molecule_list = ['H', 1, 'C', 2, 'H', 3, 'O', 2]

到目前为止,这个方法工作得很好,但是如果我输入一个包含两个字母的元素,例如Na (Na),它将把它拆分为:

代码语言:javascript
复制
['N', 'a']

我正在寻找一种方法,让我的函数在字符串中查找在名为elements的字典中找到的键。我也在考虑使用正则表达式,但我不确定如何实现它。这就是我现在的函数:

代码语言:javascript
复制
def split_molecule(inputted_molecule):
    """Take the input and split it into a list
    eg: C02 => ['C', 1, 'O', 2]
    """
    # step 1: convert inputted_molecule to a list
    # step 2a: if there are two periodic elements next to each other, insert a '1'
    # step 2b: if the last element is an element, append a '1'
    # step 3: convert all numbers in list to ints

    # step 1:
    # problem: it splits Na into 'N', 'a'
    # it needs to split by periodic elements
    molecule_list = list(inputted_molecule)

    # because at most, the list can double when "1" is inserted
    max_length_of_molecule_list = 2*len(molecule_list)
    # step 2a:
    for i in range(0, max_length_of_molecule_list):
        try:
            if (molecule_list[i] in elements) and (molecule_list[i+1] in elements):
                molecule_list.insert(i+1, "1")
        except IndexError:
            break
    # step2b:     
    if (molecule_list[-1] in elements):
        molecule_list.append("1")

    # step 3:
    for i in range(0, len(molecule_list)):
        if molecule_list[i].isdigit():
            molecule_list[i] = int(molecule_list[i])

    return molecule_list
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-20 15:36:08

怎么样

代码语言:javascript
复制
import re
print re.findall('[A-Z][a-z]?|[0-9]+', 'Na2SO4MnO4')

结果

代码语言:javascript
复制
['Na', '2', 'S', 'O', '4', 'Mn', 'O', '4']

Regex解释说:

代码语言:javascript
复制
Find everything that is either

    [A-Z]   # A,B,...Z, ie. an uppercase letter
    [a-z]   # followed by a,b,...z, ie. a lowercase latter
    ?       # which is optional
    |       # or
    [0-9]   # 0,1,2...9, ie a digit
    +       # and perhaps some more of them

这个表达式非常愚蠢,因为它接受任意的“元素”,比如"Xy“。您可以通过将[A-Z][a-z]?部件替换为实际的元素名称列表来改进它,这些名称由|分隔,如Ba|Na|Mn...|C|O

当然,正则表达式只能处理非常简单的公式,例如

代码语言:javascript
复制
  8(NH4)3P4Mo12O40 + 64NaNO3 + 149NH4NO3 + 135H2O

你需要一个真正的解析器,比如pyparsing (一定要检查“Examples”下面的“化学公式”)。祝好运!

票数 5
EN

Stack Overflow用户

发布于 2012-03-20 15:56:38

这样的表达式将匹配所有感兴趣的部分:

代码语言:javascript
复制
[A-Z][a-z]*|\d+

您可以将它与re.findall一起使用,然后为没有任何值的原子添加量词。

或者,您也可以使用正则表达式:

代码语言:javascript
复制
molecule = 'NaHC2H3O2'
print re.findall(r'[A-Z][a-z]*|\d+', re.sub('[A-Z][a-z]*(?![\da-z])', r'\g<0>1', molecule))

输出:

代码语言:javascript
复制
['Na', '1', 'H', '1', 'C', '2', 'H', '3', 'O', '2']

sub在所有后面没有跟数字的原子后面添加一个1

票数 2
EN

Stack Overflow用户

发布于 2012-03-20 15:58:00

非正则表达式方法,这是有点老套的,可能不是最好的,但它是有效的:

代码语言:javascript
复制
import string

formula = 'HC2H3O2Na'
m_list = list()
for x in formula:
   if x in string.lowercase:
      m_list.append(formula[formula.index(x)-1]+x)
      _ = m_list.pop(len(m_list)-2)
   else:
      m_list.append(x)
print m_list
['H', 'C', '2', 'H', '3', 'O', '2', 'Na']
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9782835

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档