我有一些日期,我可以从以下日期提取当天:
df_dates = data_frame(
day = seq.int(31),
suffix = c(
"st",
"nd",
"rd",
rep("th", 17),
"st",
"nd",
"rd",
rep("th", 7),
"st"
)
)
我想根据需要格式化后缀为“th”,“rd”或“nd”的日期。所以,“第一”,“第二”,“第三”等等。有没有一种简单的方法来实现这一目标,还是我必须列举规则?
我可以将其实现为强力查找:
$('.form-group input').blur(function() {
var value = $(this).val();
if (value == "" || value == undefined) {
$(this).parents('.form-group').addClass('has-error');
}
});
但欢迎更优雅的解决方案。
答案 0 :(得分:6)
这是一个tidyverse解决方案,使用矢量化SQL样式if-else函数case_when
。
library(dplyr)
library(lubridate)
append_date_suffix <- function(dates){
dayy <- day(dates)
suff <- case_when(dayy %in% c(11,12,13) ~ "th",
dayy %% 10 == 1 ~ 'st',
dayy %% 10 == 2 ~ 'nd',
dayy %% 10 == 3 ~'rd',
TRUE ~ "th")
paste0(dayy, suff)
}
使用今天的日期测试
append_date_suffix(as.Date(-10:10, now()))
[1] "4th" "5th" "6th" "7th" "8th" "9th" "10th"
[8] "11th" "12th" "13th" "14th" "15th" "16th" "17th"
[15] "18th" "19th" "20th" "21st" "22nd" "23rd" "24th"
根据要求,时间:
library(microbenchmark)
microbenchmark(scales::ordinal(as.Date(-1000:1000, now())),
append_date_suffix(as.Date(-1000:1000, now())))
Unit: milliseconds
expr min lq mean median uq max neval
scales::ordinal(as.Date(-1000:1000, now())) 45.89437 46.408347 47.316820 46.734974 48.228251 53.14592 100
append_date_suffix(as.Date(-1000:1000, now())) 1.39770 1.451481 1.549895 1.490646 1.530105 3.52757 100
请求的实际时间如下。我们不测量as.Date()
的速度,我们需要确保两种方法输出相同的东西:
ads_cw <- function(dates){
dayy <- day(dates)
suff <- case_when(dayy %in% c(11,12,13) ~ "th",
dayy %% 10 == 1 ~ 'st',
dayy %% 10 == 2 ~ 'nd',
dayy %% 10 == 3 ~'rd',
TRUE ~ "th")
paste0(dayy, suff)
}
ads_so <- function(dates) {
dayy <- day(dates)
scales::ordinal(dayy)
}
dates <- as.Date(-1000:1000, now())
microbenchmark(ads_cw(dates), ads_so(dates))
## Unit: milliseconds
## expr min lq mean median uq max neval cld
## ads_cw(dates) 1.226038 1.267377 1.526139 1.329442 1.505056 3.180228 100 a
## ads_so(dates) 7.270987 7.632697 8.275644 8.077106 8.816440 10.571275 100 b
答案代码仍然比scales::ordinal
快,但现在基准是诚实的。
值得注意的是,如果你想仅使用数字向量进行比较,它仍然快〜7倍。
just_nums <- function(n){
suff <- case_when(n %in% c(11,12,13) ~ "th",
n %% 10 == 1 ~ 'st',
n %% 10 == 2 ~ 'nd',
n %% 10 == 3 ~'rd',
TRUE ~ "th")
paste0(n, suff)
}
microbenchmark(scales::ordinal(1:1000),
just_nums(1:1000))
Unit: microseconds
expr min lq mean median uq max neval
scales::ordinal(1:1000) 4411.144 4483.191 5055.2170 4560.647 4738.355 45206.038 100
just_nums(1:1000) 666.407 687.305 788.3066 713.319 746.347 1808.943 100
答案 1 :(得分:1)
这是一个小帮助:
getOrdinalNumber <- function(num) {
result <- ""
if (!(num %% 100 %in% c(11, 12, 13))) {
result <- switch(as.character(num %% 10),
"1" = {paste0(num, "st")},
"2" = {paste0(num, "nd")},
"3" = {paste0(num, "rd")},
paste0(num,"th"))
} else {
result <- paste0(num, "th")
}
result
}
该功能的工作方式如下:
num %% 100
表示x mod y,因此您在将一个数字除以另一个数字后检查余数。例如,21 %% 100
为21.所以21不是%in% c(11,12,13)
,而!
使语句TRUE
和switch
参数添加“st”
如果我们有num <- 11
,则第一次检查11 %% 100
为11,因此添加了“th”(因此我们处于else
循环中)
这只是你的一个起点,因为你可以使用这个功能不仅对单个数字,而且对整个向量。 但那是你的工作: - )