Ruby 检测重复事件中的冲突
我正在编写一个需要检查冲突的日历应用程序 在重复条目之间。每个条目对象都有一个recurrences()方法 它返回一个范围数组-每个范围包含开始和结束 每次未来发生的次数 我需要检查新条目和现有条目之间是否存在冲突。我是 执行此操作时,请检查新的 条目与现有条目将来出现的冲突:Ruby 检测重复事件中的冲突,ruby,calendar,constraints,recurrence,Ruby,Calendar,Constraints,Recurrence,我正在编写一个需要检查冲突的日历应用程序 在重复条目之间。每个条目对象都有一个recurrences()方法 它返回一个范围数组-每个范围包含开始和结束 每次未来发生的次数 我需要检查新条目和现有条目之间是否存在冲突。我是 执行此操作时,请检查新的 条目与现有条目将来出现的冲突: def conflicts?(other) conflicts = 0 recurrences.each do |my_rec| other.recurrences.each do |other_rec
def conflicts?(other)
conflicts = 0
recurrences.each do |my_rec|
other.recurrences.each do |other_rec|
start, finish = other_rec.first, other_rec.last
conflicts += 1 if my_rec.include?(start) || my_rec.include?(finish)
end
end
conflicts > 0
end
recurrences()默认返回开始时间之间的所有事件
和开始时间+1年
问题是这种方法不是很有效。仅比较两个条目,每个条目在一年内每天重复一次,就可以进行365*365次比较(在我的机器上,这需要4秒以上的时间)。可以有任意数量的现有条目将新条目与so进行比较
我现在的方法是无用的
我没有计算机科学或数学背景,但我一直
在阅读各种算法教科书时,我一直找不到答案
优化方法的方法。还有其他人有什么想法吗
谢谢
Dave首先,您可以通过提前返回函数来改善这一点:
def conflicts?(other)
conflicts = 0
recurrences.each do |my_rec|
other.recurrences.each do |other_rec|
start, finish = other_rec.first, other_rec.last
return true if my_rec.include?(start) || my_rec.include?(finish)
end
end
false
end
但是,这不会提高算法的平均性能,但在发生冲突时只会导致一次比较。唯一的选择是尽早检测“简单”碰撞。很像
- 将重复类型(每周、每天、每月)存储到重复对象中
- 如果这两种情况每天都会发生,那么找出第一天可能发生冲突的地方。示例:每日,a:一月至七月,b:五月至十月应仅检查五月一日是否存在时间冲突。如果没有发生冲突,则不需要检查其他冲突
- 对不同星座(周-周、日-周、日-年)执行相同操作
- 避免写
和周日
-周日
与周日(x,y)
相同周日(y,x)
- 如果找不到匹配的方法,则必须使用上面给出的方法作为备用方法
假设重复事件是可排序的,您可以按O(n*log(n)对它们进行排序,并且只与相邻事件进行比较。下面是一个开始:
def conflicts?(other)
conflicts = 0
# Generate all recurrences and sort
all_recurrences = recurrences + other.recurrences
all_recurrences.sort!
# Keep track of what immediate neighbors could be conflicting
conflicting = []
all_recurrences.each do |my_rec|
conflicting.each do |other_rec| do
start, finish = other_rec.first, other_rec.last
if my_rec.include?(start) || my_rec.include?(finish) then
# TODO update conflicting array: add my_rec + other_rec if conflicting
conflicts += 1
else
# TODO remove other_rec if not conflicting
end
end
end
conflicts > 0
end
require 'set' #ruby standard lib
first_dates = Set.new [1,2] #where 1 and 2 are your sample dates, in an array
second_dates = Set.new [2,3] #where 2 and 3 are your sample dates,
first_dates.intersection( second_dates ).empty? #if empty, then no conflict