Boost ICL映射是否可以按间隔替换值?

alf*_*lfC 3 c++ boost boost-icl

Boost.ICLinterval_map有两种行为:+=insert。两者在不同的上下文中都是有用的。第一个将两个现有间隔的公共交点处的值相加。第二种方法仅在先前未分配的间隔中引入新值(在先前分配的间隔中保留值)。

但是,我需要一种与众不同的行为,这样,在下面的示例中,(1.,2.)->1 , (2.5,3.)->3, (3.,5.)->2我得到了期望的,而不是得到了不需要的间隔图(1.,2.)->1 , (2.5,5.)->3

也就是说,新插入的值替换了旧值吗?我如何声明interval_map要获得替换行为?

#include<boost/icl/interval_map.hpp>
int main(){
    boost::icl::interval_map<double, int> joined_map;
    joined_map.insert( std::make_pair(
        boost::icl::interval<double>::open(1., 2.),
        1
    ));
    joined_map.insert( std::make_pair(
        boost::icl::interval<double>::open(3., 5.),
        2
    ));
    joined_map.insert( std::make_pair(
        boost::icl::interval<double>::open(2.5, 5.),
        3
    )); // this line doesn't replace the old value 2, it keeps it.
}
Run Code Online (Sandbox Code Playgroud)

奖金:boost::icl::map应该做什么?如何使用?


编辑1:这是使用C ++ 11的更明确和简化的示例代码

#include<boost/icl/interval_map.hpp>
#include<iostream>

namespace icl = boost::icl;
using interval = icl::interval<double>;

int main(){
    icl::interval_map<double, int> joined_map;

    joined_map.insert({interval::open(1., 2.), 1});
    joined_map.insert({interval::open(3., 5.), 2});
    joined_map.insert({interval::open(2.5, 5.), 3}); 
    // ^^^^ this line doesn't replace the old value 2! it keeps it.
    for(auto e: joined_map) std::cout << e.first <<' '<< e.second <<'\n';
    // prints: (1,2) 1 \\ (2.5,3] 3 \\ (3,5) 2
    // desired: (1,2) 1 \\ (2.5,5] 3  // value 2 gone
}
Run Code Online (Sandbox Code Playgroud)

编辑2: 基于@JorgeBellon的答案的完整解决方案

#include<boost/icl/interval_map.hpp>
#include<iostream>

namespace icl = boost::icl;

template <class Type>
struct inplace_replace{// : icl::identity_based_inplace_combine<Type>{
    using first_argument_type = Type;
    void operator()(Type& object, Type const& operand) const{object = operand;}
};

using interval = icl::interval<double>;

int main(){

    icl::interval_map<
        double, int,
        icl::partial_enricher,   // Unmapped intervals have unkown value;
                                 // store identity values
        std::less             ,  // Comparator
        inplace_replace     //,  // Combination operator // IMPORTANT!!
    //  icl::inplace_erasure//,  // Extraction operator
    //  closed_interval<unsigned, std::less> // Interval type
    > joined_map;
    joined_map.add({interval::open(1. , 2.), 1}); // or joined_map+=std::make_pair(...)
    joined_map.add({interval::open(3. , 5.), 2}); // IMPORTANT: USE add, NOT insert!!
    joined_map.add({interval::open(2.5, 5.), 3}); 
    // ^^^^ this line now replaces the old value 2
    for(auto e: joined_map) std::cout << e.first <<' '<< e.second <<'\n';
    // prints: (1,2) 1 \\ (2.5,5] 3  // value 2 gone
}
Run Code Online (Sandbox Code Playgroud)

seh*_*ehe 5

您可以在插入之前简单地擦除打算覆盖的部分的内容:

看到它住在Coliru

#include <iostream>
#include <boost/icl/interval_map.hpp>

namespace icl = boost::icl;

int main()
{
    icl::interval_map<double, int> joined_map;
    using ival = icl::interval<double>;

    joined_map.add({ival::open(1., 2.), 1});
    joined_map.add({ival::open(3., 5.), 2});
    std::cout << "#1: "; for(auto el : joined_map) std::cout << el.first << ": " << el.second << ", "; std::cout << "\n";

    joined_map.erase(ival::open(3., 6.));
    joined_map.add({ival::open(3., 6.), 4});
    std::cout << "#2: "; for(auto el : joined_map) std::cout << el.first << ": " << el.second << ", "; std::cout << "\n";
}
Run Code Online (Sandbox Code Playgroud)

打印:

#1: (1,2): 1, (3,5): 2, 
#2: (1,2): 1, (3,6): 4, 
Run Code Online (Sandbox Code Playgroud)

我相信这就是您想要的。


旧答案文本,以供漫画浮雕将来参考

我感觉到interval_map的语义不是您所期望的。我现在已经玩了一点,不能说我理解它,但是我知道足以看到没有简单的1:1映射,其中插入的事物和存储在容器中的“元素”。

因此,与std :: map出现许多令人惊讶的差异

  • 没有operator[],但operator[]已超载(返回const
  • find()返回一个const_iterator(大概是因为它可以返回以某种方式从实际数据派生的“虚拟节点”)。因此,您不能只是期望map.erase(find(k))-您必须按键或间隔明确删除。
  • 除了之外,还有addsubtract方法insert

演示代码:

#include <iostream>
#include <boost/icl/interval_map.hpp>
#include <boost/icl/interval.hpp>

namespace icl = boost::icl;

int main()
{
    icl::interval_map<double, int,
       icl::partial_absorber,
       /*ICL_COMPARE Compare =*/ ICL_COMPARE_INSTANCE(ICL_COMPARE_DEFAULT, double), 
       /*ICL_COMBINE Combine =*/ ICL_COMBINE_INSTANCE(icl::inplace_plus, int), 
       /*ICL_SECTION Section =*/ ICL_SECTION_INSTANCE(icl::inter_section, int)
        > joined_map;
    using ival = icl::interval<double>;

    joined_map.add({ival::open(1., 2.), 1});
    joined_map.add({ival::open(3., 5.), 2});
    std::cout << "#1: "; for (auto el : joined_map) std::cout << el.first << ": " << el.second << ", "; std::cout << "\n";
    auto clone1 = joined_map;

    joined_map.add({3., 2});
    std::cout << "#2: "; for (auto el : joined_map) std::cout << el.first << ": " << el.second << ", "; std::cout << "\n";
    auto clone2 = joined_map;

    joined_map.add({3., 2});
    std::cout << "#3: "; for (auto el : joined_map) std::cout << el.first << ": " << el.second << ", "; std::cout << "\n";
    auto clone3 = joined_map;

    joined_map.add({ival::open(0., 6.), 10});
    std::cout << "#4: "; for (auto el : joined_map) std::cout << el.first << ": " << el.second << ", "; std::cout << "\n";
    auto clone4 = joined_map;

    for (double x = 0; x < 7; x += .5)
    {
        std::cout << x
            << "\t" << clone1(x)
            << "\t" << clone2(x)
            << "\t" << clone3(x)
            << "\t" << clone4(x) 
            << "\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

看到它在Coliru上直播,打印:

#1: (1,2): 1, (3,5): 2, 
#2: (1,2): 1, [3,5): 2, 
#3: (1,2): 1, [3,3]: 4, (3,5): 2, 
#4: (0,1]: 10, (1,2): 11, [2,3): 10, [3,3]: 14, (3,5): 12, [5,6): 10, 
0   0   0   0   0
0.5 0   0   0   10
1   0   0   0   10
1.5 1   1   1   11
2   0   0   0   10
2.5 0   0   0   10
3   0   2   4   14
3.5 2   2   2   12
4   2   2   2   12
4.5 2   2   2   12
5   0   0   0   10
5.5 0   0   0   10
6   0   0   0   0
6.5 0   0   0   0
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助