如何比较标准::地图中的所有项目?
How to compare all items in std::map?
我想将std::map
中的所有值相互比较。
我被困住了:对于线性容器,如矢量,我会循环索引i=1; v[i].isUniform(v[i-1])
.但我不能用地图做到这一点。我期待着听到聪明的想法。
以下是我想要完成的一些伪代码:
class MyData
{
public:
bool isUniform(const MyData& other) const
{
return this->speed == other.speed && this->ban == other.ban;
}
private:
bool ban;
int speed;
}
std::map<int, MyData> myMap;
bool allUniform = true;
for(item_1, item_2 : myMap) // how to implement this?
{
if(!item_1.isUniform(item_2))
{
allUniform = false;
}
}
最优雅(可读和高效(的方法是什么?
您可以将std::all_of
与 lambda 一起使用。 那看起来像
bool allUniform = std::all_of(std::next(myMap.begin()),
myMap.end(),
[&myMap](const auto& pair)
{ return myMap.begin()->second.isUniform(pair.second); });
这从[1, N)
开始,并调用isUniform
反对每个元素反对第一个元素。all_of
也短循环,所以一旦你有一个不均匀的结果,它就会结束。
isUniform(( 是可传递的吗?也就是说,它是否遵循任何 3 个 MyData 对象的此规则:
isUniform(A, B) && isUniform(B, C) == isUniform(A, C)
如果是这样,那么您只需要 O(n( 比较。这是我的测试代码:
#include <iostream>
#include <map>
using namespace std;
class MyData {
public:
int value;
MyData(int _value) : value(_value) {}
bool isUniform(const MyData &obj) const { return value == obj.value; }
static void checkMap(map<int, MyData> myMap) {
bool allUniform = true;
MyData * firstItem = nullptr;
for (auto it = myMap.begin(); allUniform && it != myMap.end(); ++it) {
if (firstItem == nullptr) {
firstItem = &it->second;
}
else {
allUniform = firstItem->isUniform(it->second);
}
}
cout << "All Uniform: " << (allUniform ? "Yes" : "No") << endl;
}
};
int main(int, char **) {
map<int, MyData> map1;
map<int, MyData> map2;
MyData a1(1);
MyData b1(1);
MyData b2(2);
MyData c1(1);
// Should be uniform
map1.insert(std::pair<int, MyData>(1, a1));
map1.insert(std::pair<int, MyData>(2, b1));
map1.insert(std::pair<int, MyData>(3, c1));
MyData::checkMap(map1);
// Should not be uniform
map2.insert(std::pair<int, MyData>(1, a1));
map2.insert(std::pair<int, MyData>(2, b2));
map2.insert(std::pair<int, MyData>(3, c1));
MyData::checkMap(map2);
return 0;
}
使用此输出:
$ g++ -std=c++0x Foo.cpp -o Foo && Foo
All Uniform: Yes
All Uniform: No
for(item_1, item_2 : myMap) // how to implement this?
但是,如果它们彼此相等(假设isUniform
传递和对称(,那就等于说它们都等于第一个元素。因此,您可以将每个元素与第一个元素进行比较。
天真地,我们得到:
bool allUniform(std::map<int, MyData> const &m)
{
if (m.empty()) return true; // or whatever makes sense for you
auto first = m.begin();
for (auto current = m.begin(); ++current != m.end(); )
{
if (!first->second.isUniform(current->second))
{
return false;
}
}
return true;
}
如果您不介意将第一个元素与自身进行比较,则可以简化此操作,因为实际上大多数复杂性只是避免这种情况。
使用下面std::adjacent_find
或另一个答案中的std::all_of
解决方案可能会更好。
bool allUniform(std::map<int, MyData> const &m)
{
auto first_non_uniform =
std::adjacent_find(
m.begin(), m.end(),
[](auto left, auto right)
{
return !(left->second.isUniform(right->second));
}
);
return first_non_uniform == m.end();
}
您可以使用标准算法std::adjacent_find
。
例如
#include <iostream>
#include <iomanip>
#include <map>
#include <iterator>
#include<algorithm>
class MyData
{
public:
MyData( bool ban, int speed ) : ban( ban ), speed( speed )
{
}
bool isUniform(const MyData& other) const
{
return this->speed == other.speed && this->ban == other.ban;
}
private:
bool ban;
int speed;
};
int main()
{
std::map<int, MyData> myMap =
{
{ 1, { true, 100 } }, { 2, { true, 100 } }, { 3, { true, 100 } }
};
auto it = std::adjacent_find( std::begin( myMap ), std::end( myMap ),
[]( const auto &p1, const auto &p2 )
{
return not p1.second.isUniform( p2.second );
} );
bool allUniform = it == std::end( myMap );
std::cout << std::boolalpha << allUniform << 'n';
return 0;
}
程序输出为
true
将集合中的所有元素与第一个元素进行比较:
template<class M, class F>
bool allEqual( M const& m, F&& f ) {
using std::begin; using std::end;
auto b = begin(m);
auto e = end(m);
if (b == e) return true;
for (auto it = std::next(b); it != e; ++it)
if (!f( *b, *it))
return false;
return true;
}
成对比较所有元素:
template<class M, class F>
bool pairwiseCompare( M const& m, F&& f ) {
for (auto&& a:m)
for (auto&& b:m)
{
if (std::addressof(a) == std::addressof(b))
continue;
if (!f(a,b))
return false;
}
return true;
}
这不适用于像std::vector<bool>
这样的伪容器;嗯,它会,但它会浪费自我比较元素。
相关文章:
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 无法在 CLion 中构建 C++ 项目
- 运行同一解决方案的另一个项目的项目
- CMake-按正确顺序将项目与C运行时对象文件链接
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 欧拉项目#8答案是大以获得有效答案
- 从链接列表c++中删除一个项目
- 为什么不;名字在地图上是按顺序排列的吗
- 如何比较标准::地图中的所有项目?
- 每个项目的地图是否可以具有不同的尺寸
- QML地图:大量显示的项目
- 我想使用列表中的项目在地图中搜索
- 检查最后一个项目是否通过地图密钥存在
- 在给定键 (C++) 的地图向量内查找项目
- 将项目存储在地图中的多个键下
- 如何获得项目的可视化地图
- 迭代地图和删除项目的最佳模式是什么?
- 将项目插入地图,其中还有 2 张地图
- 用户选择地图中的项目
- 从地图中获取项目并添加到向量c++中