Boost.ICL' interval_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.
}
奖金:那是boost::icl::map
应该做的吗?我该如何使用它?
答案 0 :(得分:4)
您可以在插入之前简单地删除您想要覆盖的部分的内容:
查看 Live On 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";
}
打印:
#1: (1,2): 1, (3,5): 2,
#2: (1,2): 1, (3,6): 4,
我认为这就是你想要的。
漫画救济未来参考
我感觉interval_map语义不是你所期望的。我现在已经玩了一点,并且不能说我理解它,但我知道足够明白那里不是简单的1:1映射插入的东西和&#39;元素&#39;存储在容器中。
出于这个原因,std :: map出现了许多令人惊讶的偏差
operator[]
,但operator[]
已超载(返回const
)find()
会返回const_iterator
(大概是因为它可以返回虚拟节点&#39;它以某种方式从实际数据中获得)。所以你不能指望map.erase(find(k))
- 你必须按键或间隔明确地擦除。add
和subtract
方法(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";
}
}
查看 Live On 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
希望这有帮助
答案 1 :(得分:2)
间隔图的模板参数之一是组合运算符类型。
典型示例包含使用std::set
或类似值作为值的map,然后将加成或 identity (保留现有值)用作操作。 / p>
由于默认情况下没有 overwrite 示例,因此您可以创建自己的示例并将其传递给地图:
#include <boost/icl/interval_map.hpp>
using namespace boost::icl;
// interval_map combiner functor: assigns new value if key exists
template <class Type>
struct inplace_replace : identity_based_inplace_combine<Type> {
void operator()(Type &object, const Type &operand) const {
object = operand;
}
};
template<>
inline std::string unary_template_to_string<inplace_replace>::apply() {
return "=";
}
// When adding, if interval exists, replaces value.
// When subtracting, if interval exists, removes value.
using ival_map =
interval_map<unsigned, // Key
unsigned, // Value
partial_enricher, // Unmapped intervals have unkown value; store identity values
std::less, // Comparator
inplace_replace, // Combination operator
inplace_erasure, // Extraction operator
>;
查看完整的示例:https://ideone.com/C49bDM
编辑:从identity_based_inplace_combine<Type>
(boost/icl/functors.hpp
)派生以下内容:
first_argument_type
,second_argument_type
和result_type
。identity_element
值。例如,一个集合的标识值是一个空集合,整数则为0
(在求和时很有用),等等。如果您的地图是partial_enricher
或total_enricher
,则不一定要使用它,因为在这种情况下,地图将包含任何值的条目,包括身份值。对于absorber
类型,您将需要它,因为在这种情况下,地图需要知道是否可以删除间隔。
替代方法:
// interval_map combiner functor: assigns new value if key exists
template <class Type>
struct inplace_replace {
typedef void result_type;
typedef Type& first_argument_type;
typedef const Type& second_argument_type;
void operator()(Type &object, const Type &operand) const {
object = operand;
}
};
注意:较早的boost ICL实现是从std::binary_function
派生的,而不是使用这些typedef。不幸的是,这在C ++ 11中已弃用,而在C ++ 17中已删除,因此我将尽量不要在自己的代码中使用它。最新版本实现了像上面的代码片段这样的函子。