Я пытаюсь записать метод для приложения, которое берет химическую формулу как "CH3COOH" и возвращает своего рода набор, полный их символов.
CH3COOH возвратился бы [C, H, H, H, C, O, O, H]
У меня уже есть что-то, что является видом работы, но это очень сложно и использует много кода с большим количеством вложенных если еще структуры и циклы.
Существует ли способ, которым я могу сделать это при помощи некоторого регулярного выражения с String.split или возможно в некотором другом блестящем простом коде?
Предполагая, что он правильно написан заглавными буквами, каждый символ в уравнении соответствует этому регулярному выражению:
[A-Z][a-z]*\d*
(Для людей с химическими недостатками символом элемента всегда является заглавная буква, за которой следует, необязательно, одна или две строчные буквы - например, Hg для ртути)
Вы можете записать символ элемента и номер в группах следующим образом:
([A-Z][a-z]*)(\d*)
Так что да, теоретически это может быть то, с чем могут помочь регулярные выражения. Если вы имеете дело с формулами типа C 6 H 2 (NO 2 ) 3 (CH 3 ) 3 тогда ваша работа, конечно, немного сложнее ...
Я работаю над программой, которая требует вычисления молярной массы химических формул, поэтому я создал решение, которое работает с различными формулами.
Например, "(CH3)16(Tc(H2O)3CO(BrFe3(ReCl)3(SO4)2)2)2MnO4" приведет к "16C 48H 2Tc 12H 6O 2C 2O 4Br 12Fe 12Re 12Cl 8S 32O Mn 4O" (это соединение выдумано, но оно работает!)
Этот код написан на C#, поэтому я его не выложил. Если вам интересно, я могу выложить его для вас. На самом деле я написал полный ответ, прежде чем заметил тег java.
В любом случае, он работает, по сути, рекурсивно группируя блоки атомов, объединенных скобками. Он не работает с такими коэффициентами, как 2Pb (но (Pb)2 или Pb2 работает) или заряженными соединениями, такими как OH-.
Ни в коем случае нельзя назвать его простым или элегантным. Мне нужно было рабочее решение, поэтому я знаю, что есть лучшие способы (я даже не пробовал регулярные выражения!). Но это работает с формулами, которые мне нужны, возможно, это подойдет и вам.
Вот несколько тестовых примеров, на которых я его проверил. Посмотрите на них и дайте мне знать, будет ли код на C# все еще полезен для вас. Формат (входные данные, ожидаемый выход)
("Pb ", " Pb");
("H ", " H");
("Pb2 ", " 2Pb");
("H2 ", " 2H");
("3Pb2 ", " 6Pb");
("Pb2SO4", " 2Pb S 4O");
("PbH2 ", " Pb 2H");
("(PbH2)2 ", " 2Pb 4H");
("(CCC)2 ", " 2C 2C 2C");
("Pb(H2)2 ", " Pb 4H");
("(Pb(H2)2)2 ", " 2Pb 8H");
("(Pb(H2)2)2NO3 ", " 2Pb 8H N 3O");
("(Ag(Pb(H2)2)2)2SO4 ", " 2Ag 4Pb 16H S 4O");
("Pb(CH3(CH2)2CH3)2", " Pb 2C 6H 4C 8H 2C 6H");
("Na2(CH3(CH2)2CH3)2", " 2Na 2C 6H 4C 8H 2C 6H");
("Tc(H2O)3Fe3(SO4)2", " Tc 6H 3O 3Fe 2S 8O");
("Tc(H2O)3(Fe3(SO4)2)2", " Tc 6H 3O 6Fe 4S 16O");
("(Tc(H2O)3(Fe3(SO4)2)2)2", " 2Tc 12H 6O 12Fe 8S 32O");
("(Tc(H2O)3CO(Fe3(SO4)2)2)2", " 2Tc 12H 6O 2C 2O 12Fe 8S 32O");
("(Tc(H2O)3CO(BrFe3(ReCl)3(SO4)2)2)2MnO4", " 2Tc 12H 6O 2C 2O 4Br 12Fe 12Re 12Cl 8S 32O Mn 4O");
("(CH3)16(Tc(H2O)3CO(BrFe3(ReCl)3(SO4)2)2)2MnO4", " 16C 48H 2Tc 12H 6O 2C 2O 4Br 12Fe 12Re 12Cl 8S 32O Mn 4O");
Рассматривали ли вы возможность выразить ваши химические формулы на Химическом языке разметки? Он очень универсален, и существует множество инструментов/просмотровщиков, которые могут отображать эти химические формулы или соединения в 2D и 3D.
Решение с регулярными выражениями - лучший подход, если вам нужно обрабатывать только простые случаи. В противном случае вам нужно построить что-то вроде абстрактного синтаксического дерева и оценить его или использовать польскую нотацию .
Например, формула TNT C6H2 (NO2) 3CH3
должна быть представлена как:
(+ (* C 6) (* H 2) (* (+ N (* O 2)) 3) C (+ H 3))