4

I have a list of strings representing different types of data

{{"gw12-26b-pl1", "63.6512", "0.0076", "--", "Al2O3", "%", "23.4002"},
 {"gw12-26b-pl3", "65.1182", "0.1257", "--", "SiO2", "ppm", "76.3388"}};

I want to convert the 'numerical strings' to expressions so that I can work with them. I want to end up with something like:

{{"gw12-26b-pl1", 63.6512, 0.0076, "--", "Al2O3", "%", 23.4002},
 {"gw12-26b-pl3", 65.1182, 0.1257, "--", "SiO2", "ppm", 76.3388}}

I tried to convert the whole list using ToExpression and then convert non-numeric elements back to strings but this doesn't work because it is trying to evaluate elements like gw12-26b-pl1as an expression.

Can anyone suggest an easy way to do this?

geordie
  • 3,693
  • 1
  • 26
  • 33

1 Answers1

8

A way of doing the replacement not explicitly, but implicitly with a function is to define a function t, which converts a NumberString to the number and leaves the rest untouched. Giving t the attribute Listable and it can directly be applied on the list:

SetAttributes[t, {Listable}];
t[a_String /; StringMatchQ[a, NumberString]] := ToExpression[a];
t[a_] := a;

Now you have

t@{{"gw12-26b-pl1", "63.6512", "0.0076", "--", "Al2O3", "%", 
   "23.4002"}, {"gw12-26b-pl3", "65.1182", "0.1257", "--", "SiO2", 
   "ppm", "76.3388"}}
(* {{"gw12-26b-pl1", 63.6512, 0.0076, "--", "Al2O3", "%", 
  23.4002}, {"gw12-26b-pl3", 65.1182, 0.1257, "--", "SiO2", "ppm", 
  76.3388}} *)
halirutan
  • 112,764
  • 7
  • 263
  • 474
  • Thanks! This solution is elegant because it works on nested lists. e.g. t@ {"67", "34d-45b", {"b", "27", {"ww", "11.1", {{"67.1"}, "aa", "3"}}}} – geordie May 20 '14 at 01:50
  • @geordie But rashers replace answer does work for nested lists too. Don't forget that. – halirutan May 20 '14 at 01:51
  • 3
    To speed up the code, you can use Internal`StringToDouble instead of ToExpression – Murta May 20 '14 at 01:52
  • rasher's solution works on nested lists when the levels are specified but not without errors when previous levels are re-evaluated. Or am I missing something? – geordie May 20 '14 at 01:59
  • @geordie: Yes: Fully specifying your question in the first place. In the future, when you give an example that does not fully cover your expected problem space, please try to note that. Otherwise people might waste time. – ciao May 20 '14 at 02:01
  • @rasher, certainly not trying to waste your time. Your answer was perfectly valid (I upvoted it - I don't know why you deleted it). Nonetheless, halirutan's answer is a little more elegant (don't you agree?). – geordie May 20 '14 at 02:04
  • 1
    @rasher I edited your answer and voted to undelete it. If you make your pattern restrict to strings, you don't get error messages when doing a ReplaceAll. – halirutan May 20 '14 at 02:07
  • @Murta where did you learn about Internal\StringToDouble` – Mike Honeychurch May 20 '14 at 02:44
  • @halirutan how do you vote to undelete? I think rashers answer should remain -- possibly including a Condition version in addition to PatternTest – Mike Honeychurch May 20 '14 at 02:46
  • 1
    @MikeHoneychurch here – Murta May 20 '14 at 03:30
  • @halirutan: No need to reinstate, it is just a slightly faster undecorated version of yours. I also hope the site does not in fact allow undelete on something deleted by the owner... that would be pretty lame, IMHO. +1, btw. – ciao May 20 '14 at 08:20
  • 2
    @rasher It's the other way around, because I wrote my version as an addition to your answer. And yes, I can vote for undeletion no matter whether you deleted your answer. In the end I would respect your decision, but I hope you don't take the whole issue too hard that. It always happens, and especially me, that I give a solution which is specific to the OP's needs. Often the OP then decides that a more general version was required. That's SE live I guess. – halirutan May 20 '14 at 08:43