如何仅针对键的子集有效地比较 C 中的两个字符串映射

新手上路,请多包涵

我想知道是否只有通过应用一些标准算法才能编写一个短函数来比较两个 std::map<string, string> 并在所有键值对(但一些)对为真时返回真。

例如,这两个映射应该被评估为 相等

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";

假设两个映射具有相同的大小,并且它们的所有元素都必须成对比较,除了键“X”和键“Y”存储的值。第一次尝试将是一个非常低效的双嵌套 for 循环。

我确信可以实现更好的解决方案。

原文由 linello 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 743
2 个回答

我不确定您到底在寻找什么,所以让我先给出完全相等,然后再给出关键相等。也许后者已经满足您的需求。

完全平等

(虽然可以使用 std::map 自己的比较运算符来测试标准等效性,但以下可以用作基于每个值进行比较的基础。)

完全相等可以使用 std::equalstd::operator== 测试 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";
}

关键平等

C++2003

基于以上代码,我们可以在 std::equal 调用中添加谓词:

 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";
}

C++ (C++11)

使用新的 lambda 表达式,您可以这样做:

 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);
}

C++ (C++14)

添加于 2014-03-12

使用新的通用 lambda 表达式,您可以这样做:

 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);
}

作为样式问题,您还可以直接将 C++11 和 C++14 中的 lambda 表达式作为参数内联:

 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; });
}

原文由 Sebastian Mach 发布,翻译遵循 CC BY-SA 4.0 许可协议

答案很简单,我们可以通过等价关系运算符(“==”)直接比较两个映射,就像我们比较两个变量一样。

 #include<bits/stdc++.h>
using namespace std;
int main()
{
map<string,int> m1;
map<string,int> m2;

m1["str1"]=47;
m1["str2"]=87;

m2["str1"]=47;
m2["str2"]=87;

if(m1==m2)
cout<<"maps are equal"<<endl;
else
cout<<"maps are not equal"<<endl;
}

输出: https ://i.stack.imgur.com/MCmN4.png

原文由 Nil Mani 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题