我正在编写一个需要检查冲突的日历应用程序 在经常性的条目之间。每个Entry对象都有一个recurrences()方法 返回一个范围数组 - 每个范围包含开始和结束 每个未来发生的时间。
我需要检查新条目和现有条目之间的冲突。我 这样做是通过检查新的未来发生的 与未来现有条目发生的条目冲突:
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年
问题是这种方法效率不高。比较两个条目,每个条目每天重复超过1年,导致365 * 365比较(在我的机器上需要4秒以上)。可能有任意数量的现有条目来比较新条目 我现在的方法毫无用处。我没有计算机科学或数学背景,但我一直都是 阅读有关算法的各种教科书,我一直无法找到 优化方法的方法。还有其他人有什么想法吗?
感谢
戴夫
答案 0 :(得分:2)
首先,你可以通过引起早期的函数返回来改善这一点:
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
但是,这不会提高算法的平均性能,但只会在发生冲突时进行一次比较。您唯一的选择是尽早发现“简单”碰撞。所以喜欢
day-week
和week-day
- week_day(x,y)
与day_week(y,x)
相同。正如你所看到的那样,后者的工作要多得多 - 而最坏情况下的执行时间可能相同(因为它使用原始算法作为后备)。最糟糕的情况可能是由于“不规则”的复原(例如“每天一小时后”)造成的。
答案 1 :(得分:1)
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
答案 2 :(得分:0)
一些想法:
答案 3 :(得分:0)
假设重复是可排序的,您可以在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