How to efficiently compare two maps of strings in C++ only for a subset of the keys

前端 未结 2 1302
野趣味
野趣味 2020-12-13 08:59

I\'m wondering if only by applying some standard algorithms is possible to write a short function which compare two std::map and returns t

2条回答
  •  抹茶落季
    2020-12-13 09:53

    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

    (While standard equivalence can be tested using std::map's own comparison operators, the following can be used as a base for a comparison on a per-value basis.)

    Complete equality can be tested using std::equal and std::operator== for std::pairs:

    #include 
    #include 
    #include 
    #include 
    #include 
    
    template 
    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 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 c;
        cout << "a == c? " << map_compare (a,c)  << " (should be 0)\n";
    }
    

    Key Equality

    C++2003

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

    struct Pair_First_Equal {
        template 
        bool operator() (Pair const &lhs, Pair const &rhs) const {
            return lhs.first == rhs.first;
        }
    };
    
    template 
    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 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 c;
        cout << "a == c? " << key_compare (a,c)  << " (should be 0)\n";
    }
    

    C++ (C++11)

    Using the new lambda expressions, you can do this:

    template 
    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)

    added 2014-03-12

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

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

提交回复
热议问题