2014-03-16 6 views
1

Как найти количество строк в строке? У меня есть молекулярная формула, и если буквы в верхнем регистре, это один элемент (например, H), если он имеет первую букву верхнего регистра и второй строчный регистр, чем один элемент (например, Ba), а если есть номер после элемента, я должен Добавим, что число к elmentПодстроки подстроки Python

пример: ввод: Ba4H2Ba5Li3

, если я поиск Ba он должен напечатать номер 9 (я есть BA4 и BA5, то есть 9), если я поиск H он должен напечатать 2 (одну букву H, но номер 2 после него), и Ли он должен напечатать номер 3.

+0

Что делать, если соединение представляет собой гидрид ртути (II)? Должен ли счет 'H' в' HgH2' быть 2 или 3? – user2357112

+0

@ user2357112: мое решение будет, по крайней мере, правильно считать как '{'Hg': 1, 'H': 2}'. :-) –

ответ

3

Вы можете использовать регулярные выражения, как это

data = "Ba4H2Ba5Li3" 
import re 
result = {} 
for element, count in re.findall(r"([A-Z][a-z]?)(\d*)", data): 
    result[element] = result.get(element, 0) + int(1 if count == "" else count) 
print result 
# {'H': 2, 'Ba': 9, 'Li': 3} 

Теперь вы можете получить количество каждых из элементов result, как этого

print result.get("Ba", 0) 
# 9 
print result.get("H", 0) 
# 2 
print result.get("Li", 0) 
# 3 
print result.get("Sa", 0) 
# 0 
+0

Если строка не сопровождается числом, она должна считаться 1 вхождением. – user2357112

+0

@ user2357112 Спасибо за указание. Исправлено: – thefourtheye

+0

А как насчет цианида водорода? 'HCN' анализирует как один' HC' и один 'N'. – user2357112

2

Я бы разобрать всю входную строку в словарь; регулярное выражение поможет здесь:

import re 
from collections import defaultdict 

molecule = re.compile(r'([A-Z][a-z]?)(\d*)') 

def parse_formula(f): 
    counts = defaultdict(int) 
    for name, count in molecule.findall(f): 
     counts[name] += int(count or 1) 
    return counts 

Это будет считать молекулы без цифры после символа как 1; Таким образом, «H3O» будет считаться правильно.

Теперь вы можете просто смотреть на ваши элементы:

counts = parse_formula('Ba4H2Ba5Li3') 
print counts['Ba'] 
print counts['H'] 

Демы:

>>> counts = parse_formula('Ba4H2Ba5Li3') 
>>> counts 
defaultdict(<type 'int'>, {'H': 2, 'Ba': 9, 'Li': 3}) 
>>> counts['H'] 
2 
>>> counts['Ba'] 
9 
>>> parse_formula('H3O') 
defaultdict(<type 'int'>, {'H': 3, 'O': 1}) 
+0

чем вы за помощь :) –

1

Вот несколько более надежный подход, который будет правильно обрабатывать формулы с вложенным подвыражением, такие как Na(OH)2 или Al(NO3)3:

# Loosely based on example code from 
# http://pyparsing.wikispaces.com/file/detail/chemicalFormulas.py 
from pyparsing import Group, Forward, Literal, nums, oneOf, OneOrMore, Optional, Word 

# from http://pyparsing-public.wikispaces.com/Helpful+Expressions 
# element("He") => "He" 
element = oneOf(
    """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 Lu Hf Ta W Re Os 
    Ir Pt Au Hg Tl Pb Bi Po At Rn Fr Ra Lr Rf 
    Db Sg Bh Hs Mt Ds Rg Uub Uut Uuq Uup Uuh Uus 
    Uuo La Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm 
    Yb Ac Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No""" 
) 

# integer("123") => 123 
to_int = lambda tokens: int(tokens[0]) 
integer = Word(nums).setParseAction(to_int) 

# item("He") => {"He": 1} 
# item("O2") => {"O": 2} 
item_to_dict = lambda tokens: {a:b for a,b in tokens} 
item = Group(element + Optional(integer, default=1)).setParseAction(item_to_dict) 

# allow recursive definition of formula 
Formula = Forward() 

# expr("(OH)2") => {"O": 2, "H": 2} 
lpar = Literal("(").suppress() 
rpar = Literal(")").suppress() 
expr_to_dict = lambda tokens: {el: num*tokens[1] for el,num in tokens[0].items()} 
expr = (lpar + Formula + rpar + integer).setParseAction(expr_to_dict) 

# ... complete the recursive definition 
def formula_to_dict(tokens): 
    total = {} 
    for expr in tokens: 
     for el,num in expr.items(): 
      total[el] = total.get(el, 0) + num 
    return total 
Formula <<= OneOrMore(item | expr).setParseAction(formula_to_dict) 

# Finally, wrap it in an easy-to-use function: 
def get_elements(s): 
    return Formula.parseString(s)[0] 

Вы может использовать его как:

>>> get_elements("Na(OH)2") 
{'H': 2, 'Na': 1, 'O': 2} 

>>> get_elements("Al(NO3)3") 
{'Al': 1, 'N': 3, 'O': 9} 

>>> get_elements("Ba4H2Ba5Li3") 
{'Ba': 9, 'H': 2, 'Li': 3} 
Смежные вопросы