2
$\begingroup$

Consider the following list

{"Fri", "20:00", "30/09/16", "PEC", "Zwolle", "-", "ADO", "Den", "Haag", "2.38", "3.35", "2.90", "2.5", "1.70", "2.08", "4.45", "4.10", "1.60", "1.36", "1.28", "1.53", "1.54", "2.34", "+", "36"}

This list is the interim-result from a web scrape process. All elements of the list are Strings. They need to be converted back to the same list of elements but with their original types.

First three elements to a datetime

"Fri", "20:00", "30/09/16"

Friday, 30/9/16 @ 8PM 

An unknown number of strings to one concatened string

"PEC", "Zwolle", "-", "ADO", "Den", "Haag"

"PEC Zwolle - ADO Den Haag"

An unknown number of real numbers to Real

"2.38", "3.35", "2.90", "2.5", "1.70", "2.08", "4.45", "4.10", "1.60", "1.36", "1.28", "1.53", "1.54", "2.34"

2.38, 3.35, 2.90, 2.5, 1.70, 2.08, 4.45, 4.10, 1.60, 1.36, 1.28, 1.53, 1.54, 2.34

String "+"

 "+"

One Integer number "36"

36

What is the best approach in converting strings from web imports back to their original types?

$\endgroup$
4
$\begingroup$

It's not the fastest way but assuming you don't use really huge lists this will work pretty well with PatternMatching:

list={"Fri","20:00","30/09/16","PEC","Zwolle","-","ADO","Den","Haag","2.38","3.35","2.90","2.5","1.70","2.08","4.45","4.10","1.60","1.36","1.28","1.53","1.54","2.34","+","36"};
ruleSet={
"Mon"|"Tue"|"Wed"|"Thu"|"Fri"|"Sat"|"Sun"->Null,
a_String:>DateObject[{a,{"Day","Month","YearShort"}}]/;StringMatchQ[a,RegularExpression["\\d?\\d/\\d?\\d/\\d\\d"]],
a_String:>ToExpression[a]/;StringMatchQ[a,RegularExpression["(\\d+)?\\.\\d+"]],
a_String:>TimeObject[PadRight[ToExpression/@StringSplit[a,":"],3,0]]/;StringMatchQ[a,RegularExpression["\\d?\\d:\\d\\d?(\\d\\d?)?"]]
};
refineRules={
{x___,TimeObject[c_,___],DateObject[a_,b_,d___],y___}|{___,DateObject[a_,b_,d___],TimeObject[c_,___],___}:>{x,DateObject[a,c,d],y},
{x___,a_String,b_String,y___}:>{x,a<>" "<>b,y}/;(a!="+"&&b!="+"),
a_String:>ToExpression[a]/;StringMatchQ[a,RegularExpression["\\d+"]]};
result=DeleteCases[(list/.ruleSet)//.refineRules,Null]

{DateObject[{2016, 9, 30}, TimeObject[{20, 0, 0.}, TimeZone -> 2.], TimeZone -> 2.], "PEC Zwolle - ADO Den Haag", 2.38, 3.35, 2.9, 2.5, 1.7, 2.08, 4.45, 4.1, 1.6, 1.36, 1.28, 1.53, 1.54, 2.34, "+", 36}

or in the Notebook:

enter image description here

The day-strings are deleted because the program determines the day from the date string.

If you have MMA11 you can remove the DeleteCases for the result variable and change the PatternMatching result to Nothing instead of Null.

$\endgroup$
  • $\begingroup$ Sofar I have been looking at Interpreter and GrammarRules ( definitely not fast ), when would these come into use do you think? $\endgroup$ – nilo de roock Sep 28 '16 at 23:15
  • $\begingroup$ GrammarRules should be able to do the job but its definetly slower than the plain rule-approach. Both Interpreter & GrammarRules are more for User-Input than pre-known input patterns. $\endgroup$ – Julien Kluge Sep 28 '16 at 23:25
  • $\begingroup$ If you really need performance, you'll be the best using Do-Loops, combined with Reap, Sow and Compile. $\endgroup$ – Julien Kluge Sep 28 '16 at 23:25
  • $\begingroup$ I prefer compact code over performance. $\endgroup$ – nilo de roock Sep 29 '16 at 5:21
  • $\begingroup$ Than this code is appropriate for you. $\endgroup$ – Julien Kluge Sep 29 '16 at 12: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.