使用Boost ICL查找范围包含点的所有对象

时间:2014-06-06 14:41:17

标签: c++ boost intervals

我获得了一个对象列表L,每个对象包含添加的时间,删除的时间,名称和其他一些字段。给定时间T,我想返回一个列表,该列表仅包含来自L的对象,其中T落在对象的添加时间和删除时间之间(另外,我想在同一时间搜索特定名称的所有对象)时间,但如果事情复杂化则没有必要)。我将如何使用Boost的ICL进行此操作?

1 个答案:

答案 0 :(得分:1)

假设您的对象看起来像

struct record {
    std::string name;

    using ptime = boost::posix_time::ptime;
    ptime added, removed;
};

现在,让我们添加一个方便的方法,以便我们可以使用时间间隔更轻松地工作:

    icl::interval<ptime>::interval_type validity() const { 
        icl::interval<ptime> x;
        return x.right_open(added, removed);
    }

一个简单的测试程序如下所示:

int main()
{
    ptime const start(day_clock::local_day(), { });

    std::vector<record> L {
        { "long"     , start + hours(77) , start + days(7) }   ,
        { "medium"   , start + hours(200), start + hours(236) },
        { "short"    , start + hours(220), start + hours(226) },
        { "ephemeral", start + hours(100), start + hours(101) },
    };

    for (ptime T = start; T <= (start + days(10)); T += hours(6))
    {
        std::cout << "\nT:" << T << "\t";
        std::ostream_iterator<record> out(std::cout, ";");
        std::copy_if(L.begin(), L.end(), out, [T](record const& r) { return icl::contains(r.validity(), T); });
    }
}

它以10小时为单位迭代时间点T 10天,然后打印来自L的匹配对象,看到它 Live On Coliru

T:2014-Jun-06 00:00:00  
T:2014-Jun-06 06:00:00  
T:2014-Jun-06 12:00:00  
T:2014-Jun-06 18:00:00  
T:2014-Jun-07 00:00:00  
T:2014-Jun-07 06:00:00  
T:2014-Jun-07 12:00:00  
T:2014-Jun-07 18:00:00  
T:2014-Jun-08 00:00:00  
T:2014-Jun-08 06:00:00  
T:2014-Jun-08 12:00:00  
T:2014-Jun-08 18:00:00  
T:2014-Jun-09 00:00:00  
T:2014-Jun-09 06:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-09 12:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-09 18:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-10 00:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-10 06:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-10 12:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-10 18:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-11 00:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-11 06:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-11 12:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-11 18:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-12 00:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-12 06:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-12 12:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-12 18:00:00  {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
T:2014-Jun-13 00:00:00  
T:2014-Jun-13 06:00:00  
T:2014-Jun-13 12:00:00  
T:2014-Jun-13 18:00:00  
T:2014-Jun-14 00:00:00  
T:2014-Jun-14 06:00:00  
T:2014-Jun-14 12:00:00  {medium, 2014-Jun-14 08:00:00, 2014-Jun-15 20:00:00};
T:2014-Jun-14 18:00:00  {medium, 2014-Jun-14 08:00:00, 2014-Jun-15 20:00:00};
T:2014-Jun-15 00:00:00  {medium, 2014-Jun-14 08:00:00, 2014-Jun-15 20:00:00};
T:2014-Jun-15 06:00:00  {medium, 2014-Jun-14 08:00:00, 2014-Jun-15 20:00:00};{short, 2014-Jun-15 04:00:00, 2014-Jun-15 10:00:00};
T:2014-Jun-15 12:00:00  {medium, 2014-Jun-14 08:00:00, 2014-Jun-15 20:00:00};
T:2014-Jun-15 18:00:00  {medium, 2014-Jun-14 08:00:00, 2014-Jun-15 20:00:00};
T:2014-Jun-16 00:00:00  

正如您所看到的,"ephemeral"太短了,使用这种方法完全错过了!您可能希望在插槽中遍历时间,而不是逐步遍历时间点

for (auto Slot = icl::interval<ptime>::right_open(start, start + hours(6));
     Slot.lower() <= (start + days(10)); 
     Slot = icl::interval<ptime>::right_open(Slot.upper(), Slot.upper() + hours(6)))
{
    std::cout << "\nSlot:" << Slot << "\t";
    std::ostream_iterator<record> out(std::cout, ";");
    std::copy_if(L.begin(), L.end(), out, [Slot](record const& r) { return icl::intersects(Slot, r.validity()); });
}

也可以看到 Live On Coliru ,并观察"ephemeral"不再错过的方式:

...
Slot:[2014-Jun-09 18:00:00,2014-Jun-10 00:00:00)    {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
Slot:[2014-Jun-10 00:00:00,2014-Jun-10 06:00:00)    {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};{ephemeral, 2014-Jun-10 04:00:00, 2014-Jun-10 05:00:00};
Slot:[2014-Jun-10 06:00:00,2014-Jun-10 12:00:00)    {long, 2014-Jun-09 05:00:00, 2014-Jun-13 00:00:00};
...