Ruby on Rails中两个数组的时间段同步拆分实现方案咨询
Ruby on Rails 时间段拆分同步解决方案
你可以采用「收集所有时间边界→拆分最小独立区间→匹配属性」的思路实现,逻辑清晰且能覆盖所有重叠、单边存在的场景,实现代码如下:
def sync_time_periods(time_periods_a, time_periods_b) # 辅助方法:将原始哈希转成带Date类型起止的结构,方便比较 parse_period = ->(period) { { start: Date.strptime(period[:start_date], '%d/%m/%Y'), end: Date.strptime(period[:end_date], '%d/%m/%Y'), value: period[:additional_attribute] } } a_periods = time_periods_a.map(&parse_period) b_periods = time_periods_b.map(&parse_period) # 收集所有边界点:所有时间段的开始时间、结束时间+1天 boundary_dates = [] a_periods.each do |p| boundary_dates << p[:start] boundary_dates << p[:end] + 1.day end b_periods.each do |p| boundary_dates << p[:start] boundary_dates << p[:end] + 1.day end # 去重排序 boundary_dates = boundary_dates.uniq.sort result = [] # 遍历相邻边界点,生成最小独立区间 boundary_dates.each_cons(2) do |start_date, next_start| end_date = next_start - 1.day next if start_date > end_date # 匹配a数组中包含当前区间的属性值 a_val = a_periods.find { |p| p[:start] <= start_date && p[:end] >= end_date }&.dig(:value) || 0 # 匹配b数组中包含当前区间的属性值 b_val = b_periods.find { |p| p[:start] <= start_date && p[:end] >= end_date }&.dig(:value) || 0 # 转回原格式的日期字符串 result << { start_date: start_date.strftime('%d/%m/%Y'), end_date: end_date.strftime('%d/%m/%Y'), additional_attribute_a: a_val, additional_attribute_b: b_val } end result end
代码说明
- 先把输入的两个数组的时间段都转成带Date类型的结构,避免字符串比较的错误,注意这里用
Date.strptime适配你输入的dd/mm/yyyy格式,如果你的实际日期格式不同可以调整第二个参数。 - 收集所有边界点:所有时间段的开始日期、结束日期+1天,去重排序后,相邻两个点之间就是没有任何重叠的最小独立区间。
- 遍历每个最小区间,分别去两个原始数组里找是否有包含当前区间的时间段,取对应的属性值,找不到就设为0。
- 最后把日期转回你需要的字符串格式,输出结果。
测试验证
用你给出的第一个示例调用:
time_periods_a = [ { start_date: '01/10/2021', end_date: '31/10/2021', additional_attribute: 5 }, { start_date: '01/11/2021', end_date: '30/11/2021', additional_attribute: 10 } ] time_periods_b = [ { start_date: '01/10/2021', end_date: '31/12/2021', additional_attribute: 20 } ] puts sync_time_periods(time_periods_a, time_periods_b)
输出结果和你预期的完全一致。
第二个简化的月份示例同理,边界点收集完成后拆分的区间完全匹配你给出的预期输出。
原有代码问题
你之前的代码是按两个数组的索引一一对应处理,没有考虑跨索引的重叠、两个数组长度不一致的场景,所以会出现匹配错误的情况,上述方案完全避开了这个问题。
内容的提问来源于stack exchange,提问作者MrBobologo
相关产品推荐
相关产品推荐

