7
$\begingroup$

The following string can be converted easily into a list with ToExpression

string = "{{a},{b,c,d},{e,{f,{g}}}}";
ToExpression@string

However, if the string contains characters that can be misinterpreted as syntax errors, I run in to problems.

string = "{{a},{b,c,d},{e,{[f],{g}}}}"

ToExpression throws an error since "[f]" isn't valid Wolfram.

(Side note, is that sentence grammatically correct? I would write "...isn't valid Java or C". Is it more appropriate to write "... isn't valid Wolfram Language?")

I would like to convert a string into a nested list of strings.

For reference (2242) starts with data whose Head is List and doesn't readily appear to work with nested lists, (43930) is a similar question focusing on Graph and looks promising except that the solution uses levelspec in Cases which, to my understanding, is not available in StringCases.

$\endgroup$
6
  • 1
    $\begingroup$ What should [f] to be turned into? Left untouched? $\endgroup$
    – Öskå
    Aug 19, 2014 at 17:00
  • $\begingroup$ @Öskå left untouched. The actual string I am processing has a number of characters that Mathematica would misinterpret, but it looks as if braces {} are treated as they are in M. Everything other than braces should be left as strings. $\endgroup$ Aug 19, 2014 at 17:06
  • $\begingroup$ If adding the actual problem is too broad or otherwise inappropriate, I'm happy to roll back. $\endgroup$ Aug 19, 2014 at 17:19
  • $\begingroup$ For the first case you are expecting List[List[a],List[b,c,d],List[e,List["[f]",List[g]]]] as a result? $\endgroup$
    – Öskå
    Aug 19, 2014 at 17:27
  • 1
    $\begingroup$ @Öskå close, all strings though: List[List["a"],List["b","c","d"],List["e",List["[f]",List["g"]]]]. $\endgroup$ Aug 19, 2014 at 17:44

2 Answers 2

5
$\begingroup$

Well I just saw your comment that says you want "all strings" so perhaps a different approach:

StringReplace["{{a},{b,c,d},{e,{[f],{g}}}}", 
  x : Except["{" | "," | "}"] .. :> "\"" <> x <> "\""] // ToExpression
{{"a"}, {"b", "c", "d"}, {"e", {"[f]", {"g"}}}}

If that doesn't work consider manipulating the raw box format produced by parseString:

parseString[s_String, prep : (True | False) : True] := 
  FrontEndExecute[FrontEnd`UndocumentedTestFEParserPacket[s, prep]]

fn[string_String] := 
 parseString[string][[1]] /.
  RowBox[x : {"[", __, "]"}] :> "\"" <> x <> "\"" // ToExpression

fn @ "{{a},{b,c,d},{e,{[f],{g}}}}"
{{a}, {b, c, d}, {e, {"[f]", {g}}}}
$\endgroup$
6
  • $\begingroup$ you may use SyntaxQ to check if it's a valid expression $\endgroup$
    – hieron
    Aug 19, 2014 at 18:00
  • $\begingroup$ @hieron What are you proposing? $\endgroup$
    – Mr.Wizard
    Aug 19, 2014 at 18:01
  • $\begingroup$ If[SyntaxQ@#, ToExpression@#, $Failed] & $\endgroup$
    – hieron
    Aug 19, 2014 at 18:03
  • $\begingroup$ @hieron I'm trying to understand how that is applicable to the problem at hand; are you suggesting using that as part of StringReplace or something else? $\endgroup$
    – Mr.Wizard
    Aug 19, 2014 at 18:06
  • $\begingroup$ as an alternative for the undocumented function. $\endgroup$
    – hieron
    Aug 19, 2014 at 18:10
2
$\begingroup$

@Mr.Wizard

s = StringReplace["{{a},{b,c,d},{e,{[f],{g}}}}", 
   x : Except["{" | "," | "}"] .. :> "\"" <> x <> "\""] // ToExpression
check = If[SyntaxQ@#, ToExpression@#, #] &;
ReplaceAll[s, x_String :> check@x] // InputForm

(*out*)
{{a}, {b, c, d}, {e, {"[f]", {g}}}}
$\endgroup$
2
  • $\begingroup$ Finally I see what you were getting at. +1 However this isn't apparently what the OP wants (see comments). $\endgroup$
    – Mr.Wizard
    Aug 19, 2014 at 18:48
  • $\begingroup$ I know, Pickett found the solution, although your answer was interesting too. $\endgroup$
    – hieron
    Aug 19, 2014 at 18:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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