1

I'm a beginner in R and totally lost with my homework. I suppose to create a function that takes a character string as input and returns a vector of the days of the week. The days will not return match with incorrect spelling and partial days. The days should also be in order, Monday should come before Tuesday, etc.

Sample input:

days.present(mystr = "Dinner on Monday, tuesday, Wed, or Tursday?")
days.present("SundayMonday")
days.present("Are we meeting today?")

The output should be like this:

[1] "Monday" "Tuesday"
[1] "Sunday" "Monday"
character(0)
Pinaypy
  • 37
  • 1
  • 8

2 Answers2

2
vec <- c("Dinner on Monday, tuesday, Wed, or Tursday?",
         "SundayMonday",
         "Are we meeting today?")

# a generic way of finding locale-friendly weekdays
wdays <- weekdays(Sys.Date() + 0:6)
wdays <- paste(wdays, collapse = "|")
wdays
# [1] "Thursday|Friday|Saturday|Sunday|Monday|Tuesday|Wednesday"

lapply(
  regmatches(vec, gregexpr(wdays, vec, ignore.case = TRUE)),
  tools::toTitleCase
)
# [[1]]
# [1] "Monday"  "Tuesday"
# [[2]]
# [1] "Sunday" "Monday"
# [[3]]
# list()

Another option (using the first days above, the vector of length 7).

wdays <- weekdays(Sys.Date() + 0:6)
lapply(vec, function(v) wdays[sapply(wdays, grepl, x = v, ignore.case = TRUE)])
# [[1]]
# [1] "Monday"  "Tuesday"
# [[2]]
# [1] "Sunday" "Monday"
# [[3]]
# character(0)

# also
lapply(vec, function(v) Filter(function(w) grepl(w, v, ignore.case = TRUE), wdays))
r2evans
  • 141,215
  • 6
  • 77
  • 149
  • Thank you for the quick response, but this seems too advanced for a beginner like me. :( My instructor instructed us to do this using function as we covered it in the previous lectures. Do you know if I can use `substr` to this? Thank you. – Pinaypy Mar 20 '20 at 05:58
  • (1) `substr`? I find that grossly inefficient and very un-R-like. While I could possibly come up with a way that would do it, it would be grossly inefficient. I could do it in assembly, too, but ... why. (2) Does *"too advanced"* mean you cannot use regular expressions at all? If not, then a `grep` method (as @user2332849 suggested) is feasible. If so, though, then really ... good luck, I'm not going there. – r2evans Mar 20 '20 at 06:00
  • `grep` should work also. I will keep trying and disregard the idea of `substr` :( My teacher used the `substr` in one of his function examples that's why it came to mind. He provided an example with `grep` as well. – Pinaypy Mar 20 '20 at 06:05
  • See my next suggestion. If my first one is too advanced, I'm not certain that nested `lapply`/`sapply` will be acceptable. Another option would combine those into a single `outer` and `mapply`, which ... again, perhaps more than you want. Perhaps this gives you a good start. (It's not too difficult to unwind the `lapply` and `sapply` into two nested `for` loops, using `grepl`, appending to specific `list` and vector indices.) – r2evans Mar 20 '20 at 06:24
1

Not sure if your instructor will let you use non-standard R packages. The stringr package has a cool function to extract stings called str_extract_all.

mystr1 <- "Dinner on Monday, tuesday, Wed, or Tursday?"
mystr2 <- "SundayMonday"
mystr3 <- "Are we meeting today?"

days.present <- function(mystr) {
  x <- tools::toTitleCase(mystr)
  dow <- c("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday")
  days <- paste0(dow, collapse="|")
  library(stringr)
  as.character(sort(factor(unique(stringr::str_extract_all(x, days)[[1]]), levels=dow)))
}

days.present(mystr1)
[1] "Monday"  "Tuesday"

days.present(mystr2)
[1] "Sunday" "Monday"

days.present(mystr3)
character(0)

mystr4 <- ("saturday, Saturdays, Friday, thursday, + Wednesday, TueSday, Monday, SundaY")

days.present(mystr4)
[1] "Monday"    "Wednesday" "Thursday"  "Friday"    "Saturday"
Edward
  • 10,360
  • 2
  • 11
  • 26
  • `require`/`library` -- https://stackoverflow.com/a/51263513 :-) – r2evans Mar 20 '20 at 06:25
  • Haha. Yeah - I know that. But there's a caveat which says "almost never". Here, I believe it doesn't matter as any potential error will be so easy to debug. – Edward Mar 20 '20 at 06:33
  • But `require` will never raise an error, it will (silently, here) return `FALSE` and the code will happily continue. To me, the "almost never" means: if you use it, capture its return value and do something appropriate with it. (Another point: since you're using `string::str_extract_all`, you don't even need `require` or even `library`: if the package is not installed, you will still get the error message `there is no package called 'stringr'` as needed.) (Ahh ... but you just commented it out, nice!) – r2evans Mar 20 '20 at 06:38
  • But the last line will cause an erro. – Edward Mar 20 '20 at 06:39
  • `stringr::str_extract_all(x, days)[[1]]` – Edward Mar 20 '20 at 06:39
  • It doesn't error for me, sorry, I don't understand what you mean. (BTW, it also missed `"tuesday"`, lower-case.) – r2evans Mar 20 '20 at 06:42
  • 1
    You said: "the code will happily continue." It will until the very next line. Even the OP could debug that. (BTW, no it didn't). – Edward Mar 20 '20 at 06:46
  • I skipped your `toTitleCase`, my bad, sorry about that. (And my comment about continuing was mostly generic about the unverified use of `require`. I apologize if it seems I'm nitpicking your code, I will desist. Your code works fine.) – r2evans Mar 20 '20 at 06:59
  • Hi `@Edward`, your code works, thank you so much! I have an additional question though if I try to do `mystr4 <- ("saturday, Saturdays, Friday, thursday, + Wednesday, TueSday, Monday, SundaY")` This is the output: `[1] "Saturday" "Saturday" "Friday" "Thursday" "Wednesday" "Monday" ` Is there a way to remove the duplicate days? Saturday in this example. Thank you! – Pinaypy Mar 20 '20 at 15:06
  • `@Edward`, one more requirement, :( the days should be in order, Sunday should come before Monday, and Friday before Saturday, etc. Do you know how to fix it? Thanks again for your help!! I appreciate it. – Pinaypy Mar 20 '20 at 15:20
  • Probably the easiest way is to use an ordered factor. Let me edit again...... – Edward Mar 20 '20 at 15:39
  • Thank you so much `@Edward`! I appreciate it much! I will try to apply it based on my teacher examples. Thanks again! – Pinaypy Mar 20 '20 at 16:02