7
$\begingroup$

I have a set of data read in from a larger CSV file. I want it to match the format I have from another analysis. It is structured as a series of strings with letters and numbers Here it is copy-pasted from Mathematica

{"{H, 1}", "{H, 2}", "{H, 3}", "{Mg, 1}", "{Mg, 1}", "{Mg, 1}", "{C, \
1}", "{C, 1, H, 1}", "{N, 1}", "{N, 1, H, 1}"}

I want to convert it to:

{{"H", "1"}, {"H", "2"}, {"H", "3"}, {"Mg", "1"}, {"Mg", "1"}, {"Mg", 
  "1"}, {"N", "1"}, {"N", "1", "H", "1"}}

I've tried Read and StringToStream but I haven't been able to do what I need.


I've also solved it. I wasn't on the right track, once I looked at the simple string manipulation tools after posting the question the solution jumped out at me.

data = Map[StringTrim[#, ("{" | "}") ...] &, data];
data = Map[StringSplit[#, ","] &, data]
data = StringTrim/@data
$\endgroup$
0

3 Answers 3

7
$\begingroup$

Another solution using StringSplit:

list = {"{H, 1}", "{H, 2}", "{H, 3}", "{Mg, 1}", "{Mg, 1}", "{Mg, 1}",
   "{C, 1}", "{C, 1, H, 1}", "{N, 1}", "{N, 1, H, 1}"};

StringTrim /@ StringSplit[list, {"{", ",", "}"}]
{{"H", "1"}, {"H", "2"}, {"H", "3"}, {"Mg", "1"}, {"Mg", "1"}, {"Mg", "1"}, 
 {"C", "1"}, {"C", "1", "H", "1"}, {"N", "1"}, {"N", "1", "H", "1"}}
$\endgroup$
2
  • 1
    $\begingroup$ Nice, the two calls in mine were unnecessary. Note, you'll need the second delimiter to be ", " (note the space) for the elements in the result to not have a leading space. $\endgroup$
    – rm -rf
    Commented Feb 24, 2012 at 10:22
  • $\begingroup$ @R.M I hadn't noticed the leading spaces. I decided to go for StringTrim to fix it. $\endgroup$
    – Heike
    Commented Feb 24, 2012 at 10:27
2
$\begingroup$

Here is an approach using StringSplit:

strlist = {"{H, 1}", "{H, 2}", "{H, 3}", "{Mg, 1}", "{Mg, 1}", 
  "{Mg, 1}", "{C, 1}", "{C, 1, H, 1}", "{N, 1}", "{N, 1, H, 1}"}   

Flatten[StringSplit[strlist, "{" ~~ x__ ~~ "}" :> StringSplit[x, ", "]], 1]

(* Out[1]= {{"H", "1"}, {"H", "2"}, {"H", "3"}, {"Mg", "1"}, {"Mg", "1"}, 
            {"Mg", "1"}, {"C", "1"}, {"C", "1", "H", "1"}, {"N", "1"}, 
            {"N", "1", "H", "1"}} 
*)

Per my comment under Heike's answer, a slight modification of the StringSplit solution as:

StringSplit[strlist, {"{", ", ", "}"}]

would've given the desired result. I'm including it here since she went with StringTrim to get rid of the leading space.

$\endgroup$
1
  • 1
    $\begingroup$ +1. I like this approach more than those based on ToExpression, becuase they create new symbols H, Mg, etc, which is a side effect. $\endgroup$ Commented Feb 24, 2012 at 9:33
0
$\begingroup$

I think a more flexible answer is the following:

data = {"{H, 1}", "{H, 2}", "{H, 3}", "{Mg, 1}", "{Mg, 1}", "{Mg, 1}",
 "{C, 1}", "{C, 1, H, 1}", "{N, 1}", "{N, 1, H, 1}"}
newData=Map[ToExpression,data]

That doesn't assume that the elements are of string type.

$\endgroup$
3
  • $\begingroup$ This converts the whole string into an expression, this can result in some of the letters becoming numbers if they have had a value set. Ex. if Mg=4 somewhere then it would be replaced here. $\endgroup$
    – s0rce
    Commented Feb 24, 2012 at 4:29
  • $\begingroup$ Sure. In that case, my suggestion would require you to prepare the input data in a way that is more consistent with Mathematica syntax. I.e., replace "{H, 1}" by "{\"H\", 1}" etc. $\endgroup$
    – Jens
    Commented Feb 24, 2012 at 6:48
  • $\begingroup$ I guess I should have seen that pre-existing symbol definitions would be a problem for you - otherwise you would have just said ToExpression[data]. So I agree you need string manipulation after all... $\endgroup$
    – Jens
    Commented Feb 24, 2012 at 7:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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