如何轻松检查std :: map和std :: unordered_map是否包含相同的元素

时间:2016-08-28 12:05:27

标签: c++ stl

我正在撰写Google测试单元测试,我想检查unordered_map<std::string, std::string>的内容是否与std::map<std::string, std::string>

相同

我不认为std::equal会起作用,因为std::map中的元素会按照标准排序。订单并不重要。

3 个答案:

答案 0 :(得分:14)

我认为除了浏览一张地图的所有元素并检查它们是否存在于另一张地图中之外,还有更好的方法。如果您还检查元素的数量是否相同,您就会知道地图是否完全相同。

例如:

url_namespace:url_name

答案 1 :(得分:9)

您可以使用unordered_map创建map,然后比较两个unordered_map。反之亦然。

std::unordered_map<std::string, std::string> m1;
std::map<std::string, std::string> m2;
std::unordered_map<std::string, std::string> m3(m2.begin(), m2.end());
if (m1 == m3) {}

答案 2 :(得分:1)

我会问一个明显的问题,但它确实会改变所有内容

  

map中的平等概念是否与unordered_map中的平等概念兼容?

作为不兼容定义的一个例子:

struct Point3D { std::int32_t x, y, z };

struct MapLess {
    bool operator()(Point3D const& left, Point3D const& right) const {
       return std::tie(left.x, left.y) < std::tie(right.x, right.y);
    }
};

bool operator==(Point3D const& left, Point3D const& right) {
    return std::tie( left.x,  left.z)
        == std::tie(right.x, right.z);
}

在这个(人为的)案例中,我们可以:

  • map(1, 2, 3)(1, 3, 3)
  • unordered_map(1, 2, 3)(1, 2, 4)

并且天真的查询会报告map包含在unordered_map中,因为它们都具有相同的大小会导致错误的结论,即它们是相同的。

如果存在规范的相等概念,则解决方案是在每次查找后验证查找结果与原始查找结果实际相同。

template <typename M1, typename M2>
bool equal(M1 const& left, M2 const& right) {
    if (left.size() != right.size()) { return false; }

    for (auto const& e: left) {
        auto const it = right.find(e.first);

        if (it == right.end()) { return false; }
        if (it->first != e.first) { return false; }
        if (it->second != e.second) { return false; }
    }

    return true;
}

注意:这可以用std::all和一个布尔表达式重写;这是一个品味问题,我更喜欢将其分解。

如果不存在规范的相等概念,那么反向查找可以取代相等性检查:

template <typename M1, typename M2>
bool equal(M1 const& left, M2 const& right) {
    if (left.size() != right.size()) { return false; }

    for (auto e = left.begin(), end = left.end(); e != end; ++e) {
        auto const it = right.find(e->first);

        if (it != right.end()) { return false; }
        if (left.find(it->first) != e) { return false; }
        if (it->second != e->second) { return false; }
    }

    return true;
}

这当然稍贵一点。