使用 STL Map 查找该对中第一个元素的最低键对
Find the lowest key pair for the first element in the pair using STL Map
我有一张地图,它的键是一对std::map<std::pair<int, int>, struct A> myMap
。如何查找并访问该对中每个唯一第一个元素的最低对?例如
struct A a;
myMap.insert(std::make_pair(std::pair<int, int>(1, 200), a));
myMap.insert(std::make_pair(std::pair<int, int>(1, 202), a));
myMap.insert(std::make_pair(std::pair<int, int>(2, 198), a));
myMap.insert(std::make_pair(std::pair<int, int>(2, 207), a));
我想使用的密钥是 <1, 200> 和 <2, 198>。 我不需要将它们一起返回,我只需要对每个进行操作。
谢谢你的时间!
我会选择最直接的解决方案:
auto previous_first = 0;
auto is_first_iteration = true;
for (const auto& key_value : myMap) {
const auto& key = key_value.first;
const auto& value = key_value.second;
if (is_first_iteration || key.first != previous_first) {
is_first_iteration = false;
previous_first = key.first;
// do something here!
}
}
在这里,您只需简单地迭代每个元素(我们依赖于 std::map 的属性来对元素进行排序。并且对按第一个元素排序,然后按第二个元素排序)。在每个步骤中,我们都会记住上一个第一个元素 - 如果在此步骤中相同,我们只需跳过此步骤。
@AndrewDurward指出,这个问题可以在对数时间内解决。这只是部分正确。首先,这个问题只有在最好的情况下才能在对数时间内解决。如果你有N个元素,每个元素都有不同的first
怎么办?答案中有 N 个元素,显然,您无法在对数时间内输出 N 个元素。
您可以使用自定义比较器
struct comp {
bool operator()(const std::pair<int, int>&x, const std::pair<int, int>& y ) const
{
return x.second < y.second;
}
};
std::map<std::pair<int, int>, struct A,comp > myMap;
然后找到然后将find_if
与对的第一个元素一起使用。
在您的情况下,默认情况下std::less<T>
按预期排序。
因此,以下将在没有自定义比较器的情况下工作,即只需
std::map<std::pair<int, int>, struct A > myMap;
int search_id=1; //First Element of pair, you can use entire pair too,
//but that will defeat the purpose of "lowest pair"
auto it=std::find_if(myMap.begin() , myMap.end() ,
[search_id](const std::pair<std::pair<int, int>, A>& x)
{ return x.first.first == search_id; }
);
if(it != myMap.end())
{
std::cout<<it->first.first<<" "<<it->first.second;
}
编辑:您可以将其用作循环遍历所有元素的功能
使用一个小的重载助手,你可以只使用std::lower_bound
: 住在科里鲁
列出的第一个匹配项将是您要查找的匹配项(std::pair<>
已经按(first,right)
、升序排序)。
在本例中,帮助程序是:
struct ByKeyFirst final { int value; };
inline bool operator<(Map::value_type const& v, ByKeyFirst target) {
return v.first.first < target.value;
}
如您所见,唯一"增加的复杂性"是检查是否找到匹配项,但效率应该没问题。并且您始终可以在(单元测试的)帮助程序中隐藏复杂性:
Map::const_iterator byKeyFirst(Map const& map, int target)
{
auto const e = end(map);
auto lbound = lower_bound(begin(map), e, ByKeyFirst { target });
if (lbound != e && lbound->first.first == target)
return lbound;
return e;
}
现在查找代码变为仅:
int main()
{
const Map myMap {
{ { 1, 200 }, {} },
{ { 1, 202 }, {} },
{ { 2, 198 }, {} },
{ { 2, 207 }, {} },
};
auto match = byKeyFirst(myMap, 2);
if (end(myMap) != match)
std::cout << "Matching key: (" << match->first.first << "," << match->first.second << ")n";
}
完整演示
#include <map>
#include <tuple>
#include <limits>
using namespace std;
struct A {};
using Pair = pair<int,int>;
using Map = map<Pair, A>;
namespace /*anon*/
{
struct ByKeyFirst final { int value; };
inline bool operator<(Map::value_type const& v, ByKeyFirst target) { return v.first.first < target.value; }
Map::const_iterator byKeyFirst(Map const& map, int target)
{
// you can just find the first match, Pair is already sorted by `first`, then `second`:
auto const e = end(map);
auto lbound = lower_bound(begin(map), e, ByKeyFirst { target });
if (lbound != e && lbound->first.first == target)
return lbound;
return e;
}
}
#include <iostream>
int main()
{
const Map myMap {
{ { 1, 200 }, {} },
{ { 1, 202 }, {} },
{ { 2, 198 }, {} },
{ { 2, 207 }, {} },
};
auto match = byKeyFirst(myMap, 2);
if (end(myMap) != match)
std::cout << "Matching key: (" << match->first.first << "," << match->first.second << ")n";
}
由于映射键是按字典顺序排序的,因此它们也可以被视为按其第一个元素排序(尽管有一些重复项)。 这意味着我们可以利用任何在排序范围上运行的标准算法,只要我们提供一个适当的谓词。 在这种情况下,比较键的第一个元素的谓词可以编写如下:
typedef std::map<std::pair<int, int>, struct A> myMap_t;
auto compare_first = [](
myMap_t::value_type const & p1,
myMap_t::value_type const & p2 )
{
return p1.first.first < p2.first.first;
};
完成此操作后,我们只需要选择正确的算法来迭代所需的地图元素。 我们想要映射中的第一个元素,然后是第一个不"等价"于谓词定义的元素。 这正是std::upper_bound
所做的。
auto e1 = myMap.begin();
auto e2 = std::upper_bound( e1, myMap.end(), *e1, compare_first );
或者我们可以循环它们:
for( auto it = myMap.begin(); it != myMap.end(); it = std::upper_bound( it, myMap.end(), *it, compare_first ) )
std::cout << it->first.first << " " << it->first.second << "n";
完整的代码在这里。
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- std::find,返回所有找到的值的替代方法,而不仅仅是存在重复的向量的第一个值
- 为什么在 std::map 上移动无法将元素从一个映射移动到另一个映射
- 如何仅读取文本文件中的第一个值
- 在C++中,如何在第一个"system()"结束后执行第二个"system()"?
- 查找不在标准中的第一个值::设置<int>最小-最大值
- C++:忽略第一个 cin.ignore 之后的输入
- 在C++中打印多个矢量的第一个值
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- C++第一个cout将不会打印
- 我们可以在第一个else-if条件结束后使用另一个else-if条件吗
- OpenGL:第二个VBO破坏了第一个VBO
- 为什么第一个Dynamic_cast没有投射到基类?
- OpenGL 2D游戏只绘制第二个精灵纹理而不是第一个
- C++ 为什么程序只读取第一个值
- 在我的第一个C++程序中需要一些帮助(简单)
- 将顶部堆栈元素传输到第二个堆栈的第一个
- 获取不等于特定值的向量的第一个N元素
- 如何将std ::映射的第一个N元素复制到另一个地图
- 如何在C中获取char阵列的第一个X元素?提升效果是否有改进的方法