3
$\begingroup$

Here is a string, which I call data:

(1)  Turkey   -   Italy         @ Stadio Olimpico, Rome
(2)  Wales    -   Switzerland   @ Olympic Stadium, Baku

I can process it as follows:

StringReplace[
  "(" ~~ id__ ~~ ")" ~~ Whitespace ~~ Shortest[team1__] ~~ 
    Whitespace ~~ "-" ~~ Whitespace ~~ Shortest[team2__] ~~ 
    Whitespace ~~ "@ " ~~ venue__ :> <|"id" -> ToExpression[id], 
    "team1" -> team1, "team2" -> team2, "venue" -> venue|>] /@ 
 ImportString[data, "Lines"]

But the result of each is a StringExpression:

(* {StringExpression[<|"id" -> 1, "team1" -> "Turkey", 
   "team2" -> "Italy", "venue" -> "Stadio Olimpico, Rome"|>], 
 StringExpression[<|"id" -> 2, "team1" -> "Wales", 
   "team2" -> "Switzerland", "venue" -> "Olympic Stadium, Baku"|>]} *)

I can use Identity@@@ to remove StringExpression, but the fact that StringReplace gives me such a weird output makes me think that it must not be right tool for the job. Is there a better way?

$\endgroup$

3 Answers 3

5
$\begingroup$

Regular expressions are useful:

data = "(1)  Turkey   -   Italy         @ Stadio Olimpico, Rome
(2)  Wales    -   Switzerland   @ Olympic Stadium, Baku"

Association @@@ 
 StringCases[data, 
  RegularExpression[
    "\\(([0-9])\\)\\s+(\\w+)[\\s-]+(\\w+)[\\s@]+(\\S+.+)"] -> 
     {"id" ->"$1", "team1" -> "$2", "team2" -> "$3", "venue" -> "$4"}]

{<|"id" -> "1", "team1" -> "Turkey", "team2" -> "Italy", "venue" -> "Stadio Olimpico, Rome"|>, <|"id" -> "2", "team1" -> "Wales", "team2" -> "Switzerland", "venue" -> "Olympic Stadium, Baku"|>}

Alternatively,

StringCases[#, 
    "(" ~~ id__ ~~ ")" ~~ Whitespace ~~ Shortest[team1__] ~~ 
      Whitespace ~~ "-" ~~ Whitespace ~~ Shortest[team2__] ~~ 
      Whitespace ~~ "@ " ~~ venue__
     :> <|"id" -> id, "team1" -> team1, "team2" -> team2, "venue" -> venue|>][[1]] & /@ ImportString[data, "Lines"]

{<|"id" -> "1", "team1" -> "Turkey", "team2" -> "Italy", "venue" -> "Stadio Olimpico, Rome"|>, <|"id" -> "2", "team1" -> "Wales", "team2" -> "Switzerland", "venue" -> "Olympic Stadium, Baku"|>}

$\endgroup$
4
$\begingroup$

You can also use StringSplit + StringTrim:

values = StringTrim /@ StringSplit[ImportString[data, "Lines"], "(" | ")" | "-" | "@"];

keys = {"id", "team1", "team2", "venue"};

AssociationThread[keys, #] & /@ values
{<|"id" -> "1", "team1" -> "Turkey", "team2" -> "Italy",
   "venue" -> "Stadio Olimpico, Rome"|>,
 <|"id" -> "2", "team1" -> "Wales", "team2" -> "Switzerland", 
   "venue" -> "Olympic Stadium, Baku"|>}
$\endgroup$
1
$\begingroup$

StringReplace returns a String or StringExpression.

If you want to return something else use StringCases.

$\endgroup$

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.