linello - 1 year ago 148

C++ Question

I'm wondering if only by applying some standard algorithms is possible to write a short function which compare two

`std::map<string, string>`

For example, these two maps should be evaluated as

`map<string,string> m1, m2;`

m1["A"]="1";

m2["A"]="1";

m1["B"]="2";

m2["B"]="2";

m1["X"]="30";

m2["X"]="340";

m1["Y"]="53";

m2["Y"]="0";

Suppose that the two maps have same size and all their elements must be pairwise compared except the value stored by the key "X" and key "Y". A first attempt would be a very inefficient double nested for loop.

I'm sure a better solution can be achieved.

Recommended for you: Get network issues from **WhatsUp Gold**. **Not end users.**

Answer Source

I am not sure what exactly you are looking for, so let me first give complete equality and then key equality. Maybe the latter fits your needs already.

Complete equality can be tested using `std::equal`

and `std::operator==`

for `std::pair`

s:

```
#include <utility>
#include <algorithm>
#include <string>
#include <iostream>
#include <map>
template <typename Map>
bool map_compare (Map const &lhs, Map const &rhs) {
// No predicate needed because there is operator== for pairs already.
return lhs.size() == rhs.size()
&& std::equal(lhs.begin(), lhs.end(),
rhs.begin());
}
int main () {
using namespace std;
map<string,string> a, b;
a["Foo"] = "0";
a["Bar"] = "1";
a["Frob"] = "2";
b["Foo"] = "0";
b["Bar"] = "1";
b["Frob"] = "2";
cout << "a == b? " << map_compare (a,b) << " (should be 1)\n";
b["Foo"] = "1";
cout << "a == b? " << map_compare (a,b) << " (should be 0)\n";
map<string,string> c;
cout << "a == c? " << map_compare (a,c) << " (should be 0)\n";
}
```

Based on the above code, we can add a predicate to the `std::equal`

call:

```
struct Pair_First_Equal {
template <typename Pair>
bool operator() (Pair const &lhs, Pair const &rhs) const {
return lhs.first == rhs.first;
}
};
template <typename Map>
bool key_compare (Map const &lhs, Map const &rhs) {
return lhs.size() == rhs.size()
&& std::equal(lhs.begin(), lhs.end(),
rhs.begin(),
Pair_First_Equal()); // predicate instance
}
int main () {
using namespace std;
map<string,string> a, b;
a["Foo"] = "0";
a["Bar"] = "1";
a["Frob"] = "2";
b["Foo"] = "0";
b["Bar"] = "1";
b["Frob"] = "2";
cout << "a == b? " << key_compare (a,b) << " (should be 1)\n";
b["Foo"] = "1";
cout << "a == b? " << key_compare (a,b) << " (should be 1)\n";
map<string,string> c;
cout << "a == c? " << key_compare (a,c) << " (should be 0)\n";
}
```

Using the new lambda expressions, you can do this:

```
template <typename Map>
bool key_compare (Map const &lhs, Map const &rhs) {
auto pred = [] (decltype(*lhs.begin()) a, decltype(a) b)
{ return a.first == b.first; };
return lhs.size() == rhs.size()
&& std::equal(lhs.begin(), lhs.end(), rhs.begin(), pred);
}
```

^{added 2014-03-12}

Using the new generic lambda expressions, you can do this:

```
template <typename Map>
bool key_compare (Map const &lhs, Map const &rhs) {
auto pred = [] (auto a, auto b)
{ return a.first == b.first; };
return lhs.size() == rhs.size()
&& std::equal(lhs.begin(), lhs.end(), rhs.begin(), pred);
}
```

As a style-matter, you can also inline the lambda expressions in C++11 and C++14 directly as a parameter:

```
bool key_compare (Map const &lhs, Map const &rhs) {
return lhs.size() == rhs.size()
&& std::equal(lhs.begin(), lhs.end(), rhs.begin(),
[] (auto a, auto b) { return a.first == b.first; });
}
```

Recommended from our users: **Dynamic Network Monitoring from WhatsUp Gold from IPSwitch**. ** Free Download**