Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to split the strings of chemicals into their elements and numbers.

See this example

"Fe3O4" will be split into {"Fe","3","O","4"}

I've tried using StringSplit and various _LowerCaseQ type patters but it isn't working. I've also tried using StringSplit[#,""] to split everything and then finding the lower case characters and putting it back together but I haven't got it to work. Any solution would be greatly appreciated.

share|improve this question
up vote 14 down vote accepted

I propose:

  {"Fe3O4", "CO", "MgO", "Uut14AuO6"},
  DigitCharacter .. | (_?UpperCaseQ ~~ ___?LowerCaseQ)
{{"Fe", "3", "O", "4"}, {"C", "O"}, {"Mg", "O"}, {"Uut", "14", "Au", "O", "6"}}

Or as a RegularExpression:

  {"Fe3O4", "CO", "MgO", "Uut14AuO6"},
share|improve this answer
Very nice, simple and elegant. +1 – RunnyKine Aug 28 '14 at 17:38
@RunnyKine Thanks! :-) Hopefully it makes up for my earlier blunder. – Mr.Wizard Aug 28 '14 at 17:50
It does :). And I really like the RegEx version too. – RunnyKine Aug 28 '14 at 17:55
Patterns blow my mind. – s0rce Aug 28 '14 at 20:39
@s0rce Thanks for the Accept. – Mr.Wizard Aug 29 '14 at 2:16

I prefer one of @Mr.Wizard's solutions based on StringCases, but here is a solution using StringSplit:

StringSplit["Fe3O4", RegularExpression["(?=[A-Z]|\\d)"]]
(* {"Fe", "3", "O", "4"} *)

It splits the string at any position that is followed by an upper case letter or a digit. If multiple digits are possible:

StringSplit["Fe23O42", RegularExpression["(?=[A-Z]|(?<!\\d)\\d)"]]
(* {"Fe", "23", "O", "42"} *)

This is the same except that now a digit may not be preceded by another digit.

share|improve this answer
A powerful use of regular expressions. Is it possible to write this as a StringExpression? I can't think of a way at the moment. – Mr.Wizard Aug 29 '14 at 2:15
No, regex is the only way to express look-ahead or look-behind conditions. A shame, really, because regex patterns are ugly as sin... but it sure is nice to have the PCRE engine to draw upon for those tougher jobs. – WReach Aug 29 '14 at 5:01

You can use

chemSplit[s_String] := 
 Module[{pos = StringPosition[s, {_?UpperCaseQ, NumberString}, Overlaps -> False][[All, 1]]},
  StringSplit@StringInsert[s, " ", pos]

{"Fe", "3", "O", "4"}
share|improve this answer
elements = SortBy[ElementData[#, "Abbreviation"] & /@ ElementData[], Minus@*StringLength];
StringCases["Fe3O2", DigitCharacter .. | elements]

{"Fe", "3", "O", "2"}

(Thanks to Mr.Wizard for syntax improvements.)

share|improve this answer
There is a precision about this that I like, and I can see the effort that you put into it. +1 One could replace the second part with: StringCases[string, DigitCharacter .. | elements] if desired. Also, these string functions are set up to work with lists of patterns so I believe you can drop the Apply[Alternatives, part. – Mr.Wizard Aug 28 '14 at 19:15
@Mr.Wizard Thanks, I like your version better so I incorporated it in the answer. – C. E. Aug 28 '14 at 19:29
+1 for @*, there is always something new to learn! – ybeltukov Aug 28 '14 at 20:29

Just to be different

f = Flatten[List @@@ WolframAlpha["formula " <> #, "Result"][[1, 1]]] &;
f /@ {"Fe2O3", "MgO"}

{{"Fe", 2, "O", 3}, {"Mg", "O"}}

This approach seems to be stupid, but it can be easily extended to another chemical data (e.g. molar mass).

share|improve this answer
ybeltukov I am happy to see you posting again! Unfortunately you fell into the same trap I did; see the edit history of my answer. :^) – Mr.Wizard Aug 28 '14 at 18:41
@Mr.Wizard I also happy to join you again! When I try to correct my answer I come to your answer exactly. I propose another approach instead of deleting the post :) – ybeltukov Aug 28 '14 at 19:06

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.