这篇帖子是个不错的教学示例,因为代码风格太典型了:多数人都容易把代码写成歌词风格(复沓)。读着这样的代码总让我耳边响起:祝你生日快乐,祝你生日快乐,祝你生日快乐【谁谁谁】,祝你生日快乐。一眼望去,同一句代码一直在重复,但可能每次重复都有点小变动(儿童故事也常常是这个风格)。如果类似的代码多次重复,那么是时候考虑抽象的可能性了。
不过重复还不是最大的问题。就算重复,只要代码正确,也无大碍(歌词能正确表达出意思的话,也可以不必追求写成宋词)。最大的问题是楼上二位似乎还没有深入骨髓的向量化编程习惯。你们写的函数都是假定输入为单个日期。如果要处理多个日期,就得拿这个函数去对日期循环(*apply()
也是循环)。若我来写,我会这样写:
last_quarter_day = function(dates) {
dates = as.Date(dates)
Y = as.integer(format(dates, '%Y'))
Q = quarters(dates)
D = c(Q1 = '12-31', Q2 = '03-31', Q3 = '06-30', Q4 = '09-30')[Q]
i = Q == 'Q1'; Y[i] = Y[i] - 1
as.Date(sprintf('%d-%s', Y, D))
}
每一步操作都走是向量化的高速公路,我不必对输入日期的长度作出限制,而且跑起来还快一些。楼上制约住 chuxinyuan 的是 if ()
不可向量化(逻辑条件只能接受单值),制约住 Cloud2016 的是 switch()
也只能接受单值。这就像走一段高速,再下来走一段狭窄的土路,再上高速一样。
其它小问题如毫无必要的 stringr 依赖已经被 Cloud2016 指出来;另外就是二楼的 &
应该用 &&
。