如何在C ++中有效地比较两个字符串映射

时间:2011-12-12 10:39:18

标签: c++ stl comparison maps std

我想知道是否只应用一些标准算法就可以编写一个比较两个std::map<string, string>的短函数,如果所有键值(但有些)都为真,则返回true。

例如,这两个地图应评估为相等

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循环。 我相信可以实现更好的解决方案。

3 个答案:

答案 0 :(得分:67)

我不确定你究竟在寻找什么,所以让我首先给出完全平等,然后是关键平等。也许后者已经满足你的需求。

完全平等

可以使用std::equalstd::operator== std::pair来测试完全相等:

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

答案 1 :(得分:-1)

我认为如果您试图同时访问两个或三个或这么多相同大小的地图,那么您应该创建 itr1、itr2 并遍历所有地图 这样。

     map<char, int> :: iterator itr1, itr2;
     itr1=first.begin();
     itr2=last.begin();
     
     while(itr1!=first.end() && itr2!=last.end())
     {
         if(itr1->first!=itr2->first || itr1->second!=itr2->second)
         {
          cout<<"Akash Musky"<<endl;
         }
         else 
         {
           cout<<"Love is hard to find"<<endl;
           cout<<"You can't force anyone to love"<<endl;
          }
         itr1++;
         itr2++;
     }

答案 2 :(得分:-3)