7

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?

Murta
  • 26,275
  • 6
  • 76
  • 166

7 Answers7

12

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

ExportString[{
  {1, 2, "Three"},
  {4, 5, "{Six}"}
  }, "JSON"]
C. E.
  • 70,533
  • 6
  • 140
  • 264
  • Very interesting... sound good tks +1 – Murta Dec 05 '13 at 19:10
  • Hm... no JSON in v7 but this may be the solution. :-) – Mr.Wizard Dec 05 '13 at 19:10
  • 2
    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. – C. E. Dec 05 '13 at 19:15
  • 1
    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}}" – ssch Dec 05 '13 at 19:31
  • I have made some test. and this is just a little bit slow, but very robust against wrong parse. – Murta Dec 05 '13 at 19:46
4

How about removing heads from FullForm?

list = {{1, 2, "test3"}, {3, 4, "test4"}};
StringReplace[ToString@FullForm@list, "List[" -> "["]
  "[[1, 2, \"test3\"], [3, 4, \"test4\"]]"
István Zachar
  • 47,032
  • 20
  • 143
  • 291
  • That's quite clever (+1) but it will also expand every subexpression to FullForm as well. – Mr.Wizard Dec 05 '13 at 19:09
  • 2
    I would change "List" -> "" by "List["->"[", to avoid strings with List inside to be replaced. Tks +1 – Murta Dec 05 '13 at 19:11
  • 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. – István Zachar Dec 05 '13 at 19:48
3

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?

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Interesting behavior of string replace for multiple replacement. The rule is not applied to parts already changed, so "{}" is preserved inside strings. – Murta Dec 06 '13 at 09:42
  • @Murta Correct, or at least that was my intention. – Mr.Wizard Dec 06 '13 at 15:31
2

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 "{}".

rm -rf
  • 88,781
  • 21
  • 293
  • 472
1

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\"]]" *)
rcollyer
  • 33,976
  • 7
  • 92
  • 191
0

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.

Gregory Klopper
  • 1,370
  • 9
  • 21
  • 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. – Gregory Klopper Dec 05 '13 at 19:51
0

Here is my version:

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

Module[{$replace$},
    StringReplace[ToString@FullForm@Map[ $replace$@@#&,list,{0,1}],ToString@$replace$->""]
]
Murta
  • 26,275
  • 6
  • 76
  • 166