7
$\begingroup$

I have made this function:

conv01 = Map["["<>StringJoin@@Riffle[#,","]<>"]"&,Map[ToString,#,{2}],{0,1}]&

to convert:

list = {{1, 2, "test3"}, {3, 4, "test4"}}

to

"[[1, 2, \"test3\"], [3, 4, \"test4\"]]"

I know that I can do: conv02 = StringReplace[ToString[#], {"{" -> "[", "}" -> "]"}] & but it's not safe if I have { or } inside it.

I have tried:

conv03 = Map["[" <> ToString@Row[#, ","] <> "]" &, list, {0, 1}]

but it doesn't work and I don't understand why if this works:

"[" <> ToString@Row[{1, 2, 3, 4}, ","] <> "]"

Some clue on the last method? Some idea of simpler solution?

$\endgroup$
12
  • $\begingroup$ What's the purpose for making this change? $\endgroup$ Dec 5, 2013 at 18:48
  • $\begingroup$ @bobthechemist I don't think the first method has a good performance. And code reader is clumsy. $\endgroup$
    – Murta
    Dec 5, 2013 at 18:50
  • $\begingroup$ Do you mean {"{" -> "[", "}" -> "]"}] rather than {"{" -> "{", "}" -> "]"}]? Do I understand that your goal is to convert a Mathematica expression to a string, while replacing the list delimiters { and } with [ and ]? $\endgroup$
    – Mr.Wizard
    Dec 5, 2013 at 18:50
  • $\begingroup$ @Mr.Wizard yes.!. Corrected. And the goal is that too. Tks $\endgroup$
    – Murta
    Dec 5, 2013 at 18:51
  • $\begingroup$ I presume dados also should be list in the conv03 line? $\endgroup$
    – Mr.Wizard
    Dec 5, 2013 at 18:53

7 Answers 7

12
$\begingroup$

For working with jQuery/Javascript, you need to use JSON:

ExportString[{
  {1, 2, "Three"},
  {4, 5, "{Six}"}
  }, "JSON"]
$\endgroup$
5
  • $\begingroup$ Very interesting... sound good tks +1 $\endgroup$
    – Murta
    Dec 5, 2013 at 19:10
  • $\begingroup$ Hm... no JSON in v7 but this may be the solution. :-) $\endgroup$
    – Mr.Wizard
    Dec 5, 2013 at 19:10
  • 2
    $\begingroup$ Yes, to be clear about this: the plugin accepts JSON. JSON is the list equivalent of Javascript, so this is not a lucky coincident, it's simply the right format. $\endgroup$
    – C. E.
    Dec 5, 2013 at 19:15
  • 1
    $\begingroup$ The object equivalent even, ExportString[{"x"->{1,2,3}, "y" -> {"z"->41}}, "JSON"] gives the javascript object definition: "{\"x\" : [ 1, 2, 3 ], \"y\" : {\"z\" : 41}}" $\endgroup$
    – ssch
    Dec 5, 2013 at 19:31
  • $\begingroup$ I have made some test. and this is just a little bit slow, but very robust against wrong parse. $\endgroup$
    – Murta
    Dec 5, 2013 at 19:46
4
$\begingroup$

How about removing heads from FullForm?

list = {{1, 2, "test3"}, {3, 4, "test4"}};
StringReplace[ToString@FullForm@list, "List[" -> "["]
  "[[1, 2, \"test3\"], [3, 4, \"test4\"]]"
$\endgroup$
3
  • $\begingroup$ That's quite clever (+1) but it will also expand every subexpression to FullForm as well. $\endgroup$
    – Mr.Wizard
    Dec 5, 2013 at 19:09
  • 2
    $\begingroup$ I would change "List" -> "" by "List["->"[", to avoid strings with List inside to be replaced. Tks +1 $\endgroup$
    – Murta
    Dec 5, 2013 at 19:11
  • $\begingroup$ Thanks Murta, added! @Mr.W I am aware of it, but since the original expression seemed simple enough I assumed only atoms could appear in the lists. $\endgroup$ Dec 5, 2013 at 19:48
3
$\begingroup$

Based on the comments above this may suit you:

bracketFormat[expr_] :=
 StringReplace[
  ToString[expr, InputForm],
  {s : Shortest["\"" ~~ __ ~~ "\""] :> s, "{" -> "[", "}" -> "]"}
 ]

list = {{1, 2, "test3"}, {3, 4, "test4", "trick{}"}};

bracketFormat[list]
"[[1, 2, \"test3\"], [3, 4, \"test4\", \"trick{}\"]]"

Which will export as:

[[1, 2, "test3"], [3, 4, "test4", "trick{}"]]

A robust version of this method would be based on Leonid's simple parser:
How to write a function to remove comments from a .m source file preserving formatting such as line wrapping reasonably?

$\endgroup$
2
  • $\begingroup$ Interesting behavior of string replace for multiple replacement. The rule is not applied to parts already changed, so "{}" is preserved inside strings. $\endgroup$
    – Murta
    Dec 6, 2013 at 9:42
  • $\begingroup$ @Murta Correct, or at least that was my intention. $\endgroup$
    – Mr.Wizard
    Dec 6, 2013 at 15:31
2
$\begingroup$

You could also use a unique identifier and strip it away at the end:

With[{s = StringJoin@RandomChoice[CharacterRange["a", "z"], 30]}, 
    StringReplace[ToString[list /. {x_String :> "\"" ~~ x ~~ "\"", List -> s}], s -> ""]
]
(* [[1, 2, "test3"], [3, 4, "test4"]] *)

This works because something of the form "a"[0] is valid (i.e. a function call on a string) and only the head List is matched; not "List" or "{}".

$\endgroup$
2
  • $\begingroup$ How can I put quotes? $\endgroup$
    – Murta
    Dec 5, 2013 at 19:43
  • $\begingroup$ @Murta Change the replacement to {x_String :> "\"" ~~ x ~~ "\"", List -> s} $\endgroup$
    – rm -rf
    Dec 5, 2013 at 22:26
1
$\begingroup$

There is a v10 function that simplifies this process dramatically: TextString. It has several options for specifying how different constructs are formatted. In this case, you are looking for ListFormat, e.g.

ListFormat -> {"[", ",", "]"}

Unfortunately, it does not have an option for changing a strings format, so we have to improvise. The docs use an UpValue

quoted /: TextString[quoted[str_]] := "\"" <> str <> "\"";

But, this requires you to know where the string is in your input to begin with, so I suggest adding another UpValue and modifying the first, e.g.

quoted /: TextString[quoted[str_String]] := "\"" <> str <> "\"";
quoted /: TextString[quoted[str_]] := TextString@str;

Then, you can do

TextString[MapAll[quoted, list], ListFormat -> {"[", ",", "]"}]
(* "[[1,2,\"test3\"],[3,4,\"test4\"]]" *)
$\endgroup$
0
$\begingroup$

Here is my version:

list={{1,2,"123"},{1,2,"123"}};

Module[{$replace$},
    StringReplace[ToString@FullForm@Map[ $replace$@@#&,list,{0,1}],ToString@$replace$->""]
]
$\endgroup$
1
  • $\begingroup$ To be fair, I'll choose the answer with more upvotes. $\endgroup$
    – Murta
    Dec 5, 2013 at 19:45
0
$\begingroup$

How about this, if the source object is a String?

ToExpression@"{{2,3,\"List[thiswouldbreaksomeothermethods] test{123}\"},{3,5,\"more [stuff]\"}}" /. List :> ("[" <> StringJoin[ToString /@ {##}~Riffle~","] <> "]" &)

or if you have the source object as a Mathematica List:

{{2,3,"List[thiswouldbreaksomeothermethods] test{123}"},{3,5,"more [stuff]"}} /. List :> ("[" <> StringJoin[ToString /@ {##}~Riffle~","] <> "]" &)

Output:

"[[2,3,List[thiswouldbreaksomeothermethods] test{123}],[3,5,more [stuff]]]"

It takes a string, ignores any bracket characters in it that are parts of string contents, makes a List of it, then creates the string you want out of it with square brackets.

FYI:

In Mathematica, {...} is shorthand for List, but [...] is not a complete entity, as it represents a body of parameters to a head while lacking the head itself. Closes thing there is to it is Sequence[]. Such that {1,2,3}/.List->Sequence results in 1,2,3 set of values, but this set would still not be accurately represented with [1,2,3].

Asking Mathematica for [1, 2, 3] // FullForm generates an Incomplete expression; more input is needed. error.

$\endgroup$
1
  • $\begingroup$ This method is not sensitive like many others to the string contents since there's not a StringReplace, so "List", "List[" and other types of strings are very valid in the contents. If you have the source as a List and don't need ToExpression, then anything at all goes, even Mathematica code. $\endgroup$ Dec 5, 2013 at 19:51

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.