split_interval_map 用法,高效找到所有区间与一个点相交
split_interval_map usage, efficient find all interval intersecting a point
#include <iostream>
#include <boost/icl/split_interval_map.hpp>
using namespace std;
using namespace boost::icl;
int main()
{
split_interval_map<double, int> intervals;
intervals.add(make_pair(interval<double>::closed(0.,1.),0));
intervals.add(make_pair(interval<double>::closed(1.,2.),1));
intervals.add(make_pair(interval<double>::closed(3.,4.),2));
intervals.add(make_pair(interval<double>::closed(2.,4.),3));
intervals.add(make_pair(interval<double>::closed(1.5,3.5),4));
std::vector<double> probes = { 0.23, 1., 1.33 , 1.57, 3.49, 3.51 };
for(auto probe : probes)
{
std::cout << std::endl<< "probe " << probe << std::endl;
auto lower = intervals.lower_bound(interval<double>::closed(probe, probe));
auto upper = intervals.upper_bound(interval<double>::closed(probe, probe));
while(lower != upper)
{
std::cout << lower->second << " ";
++lower;
}
}
}
- 我得到的是指数相加。但我正在寻找包含 'probe' 的区间的所有值 (
int
s)。 (路口?)
- 我可以使用
std::set<int>
作为值来实现此目的,但在文档中指出,这对性能有巨大影响。 split_interval_map 似乎包含该信息,但我不知道如何检索它。
- 我只需要像本例中那样的高效查找。我不再需要相交的间隔范围。 boost icl 对这个来说太重了吗?
- What i get are the indices added up. But i'm looking for all the values (ints) of the interval containing 'probe'. (intersection?)
您使用您选择的组合器获得所有值(共同域值)组合。对于算术类型,这意味着求和。
如果你的co-domain是索引,显然求和是没有意义的combiner,你应该选择别的。
I could achieve this with std::set<int>
as value, but in the documentation it is stated, that this has a huge impact on performance.
一如既往,正确先于表现。如果它是你需要的,它就是你需要的。
Seems like split_interval_map contains that information but i don't know how to retrieve it it.
不适用于所选的共同域:如果间隔重叠(并且您使用 add
,而不是 set
),组合器将丢失原始信息。
I need only a highly efficient lookup like in this example. I don't need the intersecting interval ranges anymore. Is boost icl too heavy for this?
您可以使用 equal_range
而不是 lower_bound
/upper_bound
:
for (auto probe : { 0.23, 1., 1.33, 1.57, 3.49, 3.51 }) {
std::cout << "\nprobe " << probe << ": ";
for (auto& p : boost::make_iterator_range(m.equal_range(Ival::closed(probe, probe)))) {
std::cout << p.second << " ";
}
}
版画
probe 0.23:
probe 1: 1
probe 1.33: 1
probe 1.57: 4
probe 3.49: 4
probe 3.51: 3
观察:
m.add({Ival::closed(0., 1.), 0});
m.add({Ival::closed(1., 2.), 1});
m.add({Ival::closed(3., 4.), 2});
这些间隔巧妙地重叠。 [0, 1]
和 [1, 2]
有共同点 [1,1]
。您真的是说 left_open
吗? ([0, 1)
和 [1, 2)
没有重叠)。
m.add({Ival::closed(2., 4.), 3});
m.add({Ival::closed(1.5, 3.5), 4});
如果您对这结合了重叠区间中已有的值感到惊讶,您是要替换它们吗?
m.set({Ival::closed(2., 4.), 3});
m.set({Ival::closed(1.5, 3.5), 4});
备选方案、想法:
您可以一次与一组探针进行交集:
Set probes;
probes.insert(0.23);
probes.insert(1.);
probes.insert(1.33);
probes.insert(1.57);
probes.insert(3.49);
probes.insert(3.51);
std::cout << std::endl << "all: " << (m & probes) << "\n";
打印:
all: {([1,1]->1)([1.33,1.33]->1)([1.57,1.57]->4)([3.49,3.49]->4)([3.51,3.51]->3)}
(也许?)稍微优化一下:
using Map = icl::split_interval_map<double, boost::container::flat_set<int> >;
如果集要变小,请考虑为 flat_set 的序列类型指定 small_vector:
icl::split_interval_map<double,
boost::container::flat_set<int, std::less<int>,
boost::container::small_vector<int, 4>
> >;
其他一切仍然有效:Live On Coliru
完全开箱即用:您正在为几何区域建模吗?像时间轴上的间隔?或者只是轴上的线段?在那种情况下,考虑 boost::geometry::index::rtree<>
#include <iostream>
#include <boost/icl/split_interval_map.hpp>
using namespace std;
using namespace boost::icl;
int main()
{
split_interval_map<double, int> intervals;
intervals.add(make_pair(interval<double>::closed(0.,1.),0));
intervals.add(make_pair(interval<double>::closed(1.,2.),1));
intervals.add(make_pair(interval<double>::closed(3.,4.),2));
intervals.add(make_pair(interval<double>::closed(2.,4.),3));
intervals.add(make_pair(interval<double>::closed(1.5,3.5),4));
std::vector<double> probes = { 0.23, 1., 1.33 , 1.57, 3.49, 3.51 };
for(auto probe : probes)
{
std::cout << std::endl<< "probe " << probe << std::endl;
auto lower = intervals.lower_bound(interval<double>::closed(probe, probe));
auto upper = intervals.upper_bound(interval<double>::closed(probe, probe));
while(lower != upper)
{
std::cout << lower->second << " ";
++lower;
}
}
}
- 我得到的是指数相加。但我正在寻找包含 'probe' 的区间的所有值 (
int
s)。 (路口?) - 我可以使用
std::set<int>
作为值来实现此目的,但在文档中指出,这对性能有巨大影响。 split_interval_map 似乎包含该信息,但我不知道如何检索它。 - 我只需要像本例中那样的高效查找。我不再需要相交的间隔范围。 boost icl 对这个来说太重了吗?
- What i get are the indices added up. But i'm looking for all the values (ints) of the interval containing 'probe'. (intersection?)
您使用您选择的组合器获得所有值(共同域值)组合。对于算术类型,这意味着求和。
如果你的co-domain是索引,显然求和是没有意义的combiner,你应该选择别的。
I could achieve this with
std::set<int>
as value, but in the documentation it is stated, that this has a huge impact on performance.
一如既往,正确先于表现。如果它是你需要的,它就是你需要的。
Seems like split_interval_map contains that information but i don't know how to retrieve it it.
不适用于所选的共同域:如果间隔重叠(并且您使用 add
,而不是 set
),组合器将丢失原始信息。
I need only a highly efficient lookup like in this example. I don't need the intersecting interval ranges anymore. Is boost icl too heavy for this?
您可以使用 equal_range
而不是 lower_bound
/upper_bound
:
for (auto probe : { 0.23, 1., 1.33, 1.57, 3.49, 3.51 }) {
std::cout << "\nprobe " << probe << ": ";
for (auto& p : boost::make_iterator_range(m.equal_range(Ival::closed(probe, probe)))) {
std::cout << p.second << " ";
}
}
版画
probe 0.23:
probe 1: 1
probe 1.33: 1
probe 1.57: 4
probe 3.49: 4
probe 3.51: 3
观察:
m.add({Ival::closed(0., 1.), 0});
m.add({Ival::closed(1., 2.), 1});
m.add({Ival::closed(3., 4.), 2});
这些间隔巧妙地重叠。 [0, 1]
和 [1, 2]
有共同点 [1,1]
。您真的是说 left_open
吗? ([0, 1)
和 [1, 2)
没有重叠)。
m.add({Ival::closed(2., 4.), 3});
m.add({Ival::closed(1.5, 3.5), 4});
如果您对这结合了重叠区间中已有的值感到惊讶,您是要替换它们吗?
m.set({Ival::closed(2., 4.), 3});
m.set({Ival::closed(1.5, 3.5), 4});
备选方案、想法:
您可以一次与一组探针进行交集:
Set probes; probes.insert(0.23); probes.insert(1.); probes.insert(1.33); probes.insert(1.57); probes.insert(3.49); probes.insert(3.51); std::cout << std::endl << "all: " << (m & probes) << "\n";
打印:
all: {([1,1]->1)([1.33,1.33]->1)([1.57,1.57]->4)([3.49,3.49]->4)([3.51,3.51]->3)}
(也许?)稍微优化一下:
using Map = icl::split_interval_map<double, boost::container::flat_set<int> >;
如果集要变小,请考虑为 flat_set 的序列类型指定 small_vector:
icl::split_interval_map<double, boost::container::flat_set<int, std::less<int>, boost::container::small_vector<int, 4> > >;
其他一切仍然有效:Live On Coliru
完全开箱即用:您正在为几何区域建模吗?像时间轴上的间隔?或者只是轴上的线段?在那种情况下,考虑
boost::geometry::index::rtree<>