从日期数组中删除星期日,但调整星期日的删除

时间:2014-01-16 12:48:52

标签: ruby

给定一系列连续日期dates = (1..15).map { |num| Date.today + num }如何删除星期日,但是为每个删除的星期日增加额外的一天来保留原始数组的长度?

这是我的尝试,导致“堆栈级太深”异常。

def remove_sundays(dates)
  working_dates = dates.reject(&:sunday?)
  size_diff  = dates.size - working_dates.size
  unless size_diff.zero?
    last_day = working_dates.last
    working_dates = working_dates + ((1..size_diff).map { |num| last_day + num })
    remove_sundays(working_dates)
  else
    working_dates
  end
end

5 个答案:

答案 0 :(得分:2)

很难。

def remove_sundays(dates)
 dates.each.with_index do |d, i|
   if d.sunday?
     dates[i..-1] = dates[i..-1].map(&:next_day)
   end
 end
end

答案 1 :(得分:1)

麻烦就是递归,这里:

remove_sundays(working_dates)

考虑如果上次工作日期是星期日会发生什么。该函数将删除该日期,然后看到它需要添加日期,然后添加一个日期,即星期日。这会导致递归永不终止。

溶液

但这可以在没有递归的情况下完成:

def remove_sundays(dates)
  non_sundays = dates.reject(&:sunday?)
  sunday_count = dates.size - non_sundays.size
  date = dates.last + 1
  sunday_count.times.map do  
    date += 1 if date.sunday?
    non_sundays << date
    date += 1
  end
  non_sundays
end

解释

这两行与您的相同,但使用不同的变量名称:

  non_sundays = dates.reject(&:sunday?)
  sunday_count = dates.size - non_sundays.size

临时变量 date 将保留第二天添加。

  date = dates.last + 1

现在添加日期到最后,我们删除的每个星期日一个,不添加星期日。

  sunday_count.times.map do  
    date += 1 if date.sunday?
    non_sundays << date
    date += 1
  end

,最后,返回结果

  non_sundays

替代

如果日期将始终是连续的,如OP所述,则可以更简单地在没有任何星期日的情况下构建列表(而不是使用星期日构建列表,然后删除它们)。

def dates_without_sunday(date, count)
  date -= 1
  count.times.map do
    date += 1
    date += 1 if date.sunday?
    date
  end
end

dates = dates_without_sunday(Date.new(2014, 1, 16), 7)
p dates.map(&:wday)
# => [4, 5, 6, 1, 2, 3, 4]

答案 2 :(得分:1)

我改编了韦恩的回答:

def remove_sundays(dates)
  date = dates.first - 1
  dates.size.times.map do
    date += 1
    date += 1 if date.sunday?
    date
  end
end

答案 3 :(得分:0)

这是一种略有不同的方法,供您考虑。

我已将其概括为接受一系列wday,因此您可以更轻松地排除一周中任何日期的组合。位置中的“1”表示wday应包含在输出列表中。

def day_list(start_date = Date.today, day_count = 1, include_days = [1,1,1,1,1,1,1])
  date_list    = Array.new
  date         = start_date 
  wday_pattern = include_days
  while date_list.size < day_count
    date_list << date if wday_pattern[date.wday] == 1
    date = date+1
  end
  date_list
end

在行动......

2.0.0dev :001 > require 'date'
 => true 
2.0.0dev :002 > 
2.0.0dev :003 >   def day_list(start_date = Date.today, day_count = 1, include_days = [1,1,1,1,1,1,1])
2.0.0dev :004?>     date_list    = Array.new
2.0.0dev :005?>     date         = start_date 
2.0.0dev :006?>     wday_pattern = include_days
2.0.0dev :007?>     while date_list.size < day_count
2.0.0dev :008?>         date_list << date if wday_pattern[date.wday] == 1
2.0.0dev :009?>         date = date+1
2.0.0dev :010?>       end
2.0.0dev :011?>     date_list
2.0.0dev :012?>   end
 => nil 
2.0.0dev :013 > day_list
 => [#<Date: 2014-01-16 ((2456674j,0s,0n),+0s,2299161j)>] 
2.0.0dev :014 > day_list(Date.today,15,[1,1,1,1,1,1,0])
 => [#<Date: 2014-01-16 ((2456674j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-17 ((2456675j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-19 ((2456677j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-20 ((2456678j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-21 ((2456679j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-22 ((2456680j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-23 ((2456681j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-24 ((2456682j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-26 ((2456684j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-27 ((2456685j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-28 ((2456686j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-29 ((2456687j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-30 ((2456688j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-31 ((2456689j,0s,0n),+0s,2299161j)>, #<Date: 2014-02-02 ((2456691j,0s,0n),+0s,2299161j)>] 
2.0.0dev :015 > day_list(Date.today,8,[1,0,1,0,1,1,0])
 => [#<Date: 2014-01-16 ((2456674j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-17 ((2456675j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-19 ((2456677j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-21 ((2456679j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-23 ((2456681j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-24 ((2456682j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-26 ((2456684j,0s,0n),+0s,2299161j)>, #<Date: 2014-01-28 ((2456686j,0s,0n),+0s,2299161j)>] 
2.0.0dev :016 > 

答案 4 :(得分:0)

另一种方式:

require `date`
dates = (1..15).map { |num| Date.today + num }
  #            dates.day=>[17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]

new_dates = dates.reject(&:sunday?)
  # new_dates.map(&:day)=>[17,18,   20,21,22,23,24,25,   27,28,29,30,31]

next_date = new_dates.last + 1
loop do
  new_dates << next_date unless next_date.sunday?
  next_date += 1
  break if new_dates.size == dates.size
end
  # new_dates.map(&:day)=>[17,18,   20,21,22,23,24,25,   27,28,29,30,31,1,  3]

正如@Wayne所观察到的,直接生成无周日阵列更容易。这可以非常容易地完成:构建一个包含一堆连续日期的数组,去掉星期日并切掉所需的天数。要确定“束”的最小大小,请注意下一个count天最多可以包含(count + 6)/7个星期日。因此,

  today = Date.today
  count = 15

  new_dates = 1.upto(count+(count+6)/7).map \
    { |i| today+i }.reject(&:sunday?).first(count)
  # new_dates.map(&:day)=>[17,18,   20,21,22,23,24,25,  27,28,29,30,31,1,   3]