[英]How to find in c++ STL in a specific manner?
map< pair<int,int> , int > m ;
这里pair.first
和pair.second
是正数, pair.second >= pair.first
。
我想找到映射m
所有迭代器,以便针对给定的键。 Key是位于对之间的整数,例如key为2,对为[2,5]
和[1,2]
等。
例如m[1,3] = 10 , m[3,5] = 6 , m[1,8] = 9 , m[7,8] = 15
则当我搜索m.find(3)
时返回m[1,3]
, m[1,8]
, m[3,5]
迭代器。如果没有键,则返回m.end()
。
我不确定为什么要这样做,但是现在Boost Boost Interval Container库已经足够了。
假设你也许是想跟踪映射值的总 (总和)为一个特定的点,你可以简单地套用一个分裂风格结合到你的输入数据和利润:
#include <boost/icl/split_interval_map.hpp>
#include <boost/range/iterator_range.hpp>
#include <iostream>
namespace icl = boost::icl;
int main() {
using Map = icl::split_interval_map<int, int>;
using Ival = Map::interval_type;
Map m;
m.add({Ival::closed(1,3), 10});
m.add({Ival::closed(3,5), 6});
m.add({Ival::closed(1,8), 9});
m.add({Ival::closed(7,8), 15});
for (auto e : m) std::cout << e.first << " -> " << e.second << "\n";
std::cout << "------------------------------\n";
for (auto e : boost::make_iterator_range(m.equal_range(Ival::closed(3,3))))
std::cout << e.first << " -> " << e.second << "\n";
}
这将告诉我们:
[1,3) -> 19
[3,3] -> 25
(3,5] -> 15
(5,7) -> 9
[7,8] -> 24
------------------------------
[3,3] -> 25
注意如何
[3,3]
是唯一同时与输入数据中的[1,3]
和[3,5]
一致的点,因此,我们在组合集( [1,3)
, [3,3]
和(3,5]
)。 10+6+9
的总和。 因此,您看到我将问题的焦点从“如何?”转移了。 到“什么?”。 通常,它有助于陈述代码的目标,而不是特定的机制。
当然,如果您对平均值,最小值或最大值而不是总和感兴趣,那么您可能会发现自己正在编写一些自定义合并策略。
奖励如果您愿意,这里至少可以使用Boost Icl: Live On Coliru来写出解决OP中出现的问题的解决方案。 尽管它不是特别有效,但它简单而强大。
无法避免从地图开始进行线性搜索,因为如果第一个元素为{0,INT_MAX},则它匹配并且您想要的元素不一定在连续范围内,例如,如果您有{1,3 },{2,2} {3,5}仅在键为3时才需要第一个和最后一个元素。
当您到达first
大于键的元素时,可以停止搜索。
像这样(未经测试):
typedef map< pair<int,int> , int > Map;
std::vector<Map::iterator>
find(int key, const Map& m)
{
std::vector<Map::iterator> matches;
for (Map::iterator it = m.begin(), end = m.end(); it != end && key <= it->first; ++it)
{
if (it.first >= key && key <= it.second)
matches.push_back(it);
}
return matches;
}
您可以将其转换为函子并使用find_if
但我不确定是否值得。
如果只希望每个调用返回一个迭代器:
typedef map< pair<int,int> , int > Map;
Map::iterator
find(int key, const Map& m, Map::iterator it)
{
for (Map::iterator end = m.end(); it != end && key <= it->first; ++it)
{
if (it.first >= key && key <= it.second)
return it;
}
return m.end();
}
Map::iterator
find(int key, const Map& m)
{ return find(key, m, m.begin()); }
我认为可以代替(迭代器)存储(并使用)地图的相应键。 如果是这样,那么代码可能看起来像
#include <iostream>
#include <map>
#include <algorithm>
#include <vector>
#include <utility>
int main()
{
std::map<std::pair<int, int>, int> m;
m[{ 1, 3}] = 10;
m[{ 3, 5}] = 6;
m[{ 7, 8}] = 15;
typedef std::map<std::pair<int, int>, int>::value_type value_type;
typedef std::map<std::pair<int, int>, int>::key_type key_type;
int search;
auto in_range = [&search]( const value_type &value )
{
return value.first.first <= search && search <= value.first.second;
};
search = 3;
std::vector<key_type> v;
v.reserve( std::count_if( m.begin(), m.end(), in_range ) );
for ( const auto &p : m )
{
if ( in_range( p ) ) v.push_back( p.first );
}
for ( const auto &p : v )
{
std::cout << "[ " << p.first << ", " << p.second << " ]" << std::endl;
}
return 0;
}
输出是
[ 1, 3 ]
[ 3, 5 ]
考虑到key.first小于或等于key.second,其中key是映射的键。
如果您只需要迭代器即可访问映射中找到的下一个值,则可以使用std :: find_if算法,如下所示:
int key=2;
map<pair<int,int>, int>::iterator it =std::find_if(m.begin(),m.end(),
[key](pair<pair<int,int>,int> entry)
{
return (entry.first.first <= key)
&& (entry.first.second >= key);
}
);
cout << "the next value is: [" << it->first.first << "/";
cout << it->first.second << "] " << it->second << endl;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.