3

I have a string from an external file:

"start=70 end=200 step=5"

In general: it could be any similar string with arbitrary number of parameters. To avoid @Martin Mächler 's ire, see also Evaluate expression given as a string: The input format is given, I cannot change it.

Here is my solution to make this a named vector, using the no-no-no-eval:

s = "start=70 end=200 step=5"
lazyeval::lazy_eval(paste0("c(", stringr::str_replace_all(s, " ", ","),")"))
# start   end  step 
#   70   200     5 

Any more safe, elegant or Martin-pleasing alternative?

Dieter Menne
  • 10,076
  • 44
  • 67
  • 1
    I have upvoted all answers, but accepted none, because I found my own solution the best. – Dieter Menne Mar 17 '19 at 15:22
  • That's certainly fair ... any thoughts to posting and accepting your own answer? It can enrich the problem-space and perhaps help others. Thanks! (And I'm really not point-mongering, just trying to make sure questions are formally closed or updated if unresolved.) – r2evans Mar 17 '19 at 16:20

3 Answers3

4

Regular expressions to the rescue (with risks):

s <-"start=70 end=200 step=5"
re <- gregexpr("\\S+=\\d+", s)
regmatches(s, re)
# [[1]]
# [1] "start=70" "end=200"  "step=5"  

spl <- strsplit(regmatches(s, re)[[1]], "=")
setNames(as.numeric(sapply(spl, `[[`, 2)), sapply(spl, `[[`, 1))
# start   end  step 
#    70   200     5 
r2evans
  • 141,215
  • 6
  • 77
  • 149
  • I first thought something like this, but s = "" gives an ugly "character(0)". lazy_eval gives NULL. – Dieter Menne Feb 15 '19 at 19:10
  • I didn't realize there were "hostile conditions" to be considered. Perhaps with *"the input format is given"* you could provide a little more perspective on the conditions? For instance, empty strings are considered (now apparent), are non-assignment strings permitted too? String-assignments? Too far down this path resides a full parser, not something I relish implementing in straight R. – r2evans Feb 15 '19 at 19:12
  • That it nicely returned NULL on empty strings was an effect I only noted after I had posted it here. – Dieter Menne Feb 15 '19 at 21:34
  • In my experience and opinion, I prefer `character(0)` in this situation because it (1) tells me that the result should be a string, and (2) it found nothing to return, so gave me a vector of length 0. Similar to ["Contact" and the 18 hours of static](https://www.quora.com/Why-is-the-18-hour-static-not-given-significant-importance-in-the-movie-Contact-1997-Why-didnt-they-first-test-the-alien-machine-with-a-dummy), I find an empty `character(0)` to be more meaningful than `NULL`. Either way, it should be easy enough to add a conditional before `gregexpr` to check for an empty input string. – r2evans Feb 15 '19 at 21:43
2

Quite cumbersome and unintelligent, but without eval and it kinda demonstrates how it might be possibly done.

require(tidyr)

s <- "start=70 end=200 step=5"
s2 <- unlist(strsplit(s, " "))
s2 <- data.frame(s2) %>% separate(s2, c("name","value"), sep="=")
s <- s2$value
names(s) <- s2$name

result:

start   end  step 
 "70" "200"   "5"
jyr
  • 690
  • 6
  • 20
2

Another approach using scan() and base-R functions

s = "start=70 end=200 step=5"
sapply(scan(text=s,sep=" ",what=character(),quiet=T),
   function(x) { 
       x<-scan(text=x,sep="=",what=character(),quiet=T)
       setNames(as.numeric(x[2]),x[1]) },USE.NAMES = F)
Soren
  • 1,792
  • 1
  • 13
  • 16