2016-08-28 8 views
11

が含まれている場合、私は、Googleのテストユニットテストを書いています、と私はunordered_map<std::string, std::string>の内容がstd::map<std::string, std::string><p><code>std::map</code>の要素が基準に従ってソートされているため、<code>std::equal</code>は機能しません。順序は重要ではありません。</p>

と同じであるかどうかを確認したい確認する方法
+0

一方または他方を反復して、各キーの値が同じであることを確認できます。 – Chris

+1

gmockを使用していますか? https://groups.google。com/forum /#!topic/googlemock/kz4tACpCBME UnorderedElementsAreArrayはここでうまく動作します。 – FDinoff

+0

@FDinoff Google Testのみ!私はまだGmockを使用したことはありませんが、あなたのコメントは面白いです! GTockにGmockを含めるのは簡単ですか? – Aminos

答えて

14

マップのすべての要素を調べて、それらが他のマップに存在するかどうかを確認するよりも、いい方法はないと思います。要素の量が同じであることも確認すると、マップが完全に同じかどうかがわかります。例えば

template<typename K, typename E> 
bool maps_equal(const std::map<K, E> &map, const std::unordered_map<K, E> &unordered_map) { 
    return 
     map.size() == unordered_map.size() && 
     std::all_of(map.cbegin(), map.cend(), [&](const std::pair<const K, E> &item) { 
      auto iter = unordered_map.find(item.first); 
      return iter != unordered_map.end() && iter->second == item.second; 
     }); 
} 
+0

テンプレート定義(上記とstd :: map ;)に3番目のパラメータを追加しました。私のstd :: mapはカスタムコンパイラを使用してコンパイルできます。できます !テストも合格します。ありがとうございました ! – Aminos

+1

こんにちは、私はちょうどキーと値の不要なコピーを防ぐために小さな改善を行いました。 ( "std :: all_of"行が変更されました) – michalsrb

+2

@Aminos:その場合、マップと順序付けられていないマップが異なるキーの定義を使用している場合は、サイズが一致していることを確認し、もう1つは同じであることをテストするために必ずしも十分ではありません。たとえば、マップに 'X'と' Y'のキーが含まれていると仮定すると、unordered_mapには 'Y'と' Z'のキーが含まれていますが、 'X'と' Y'も同じとみなされ、 'X'と' Y' '存在する。 –

9

あなたはmapunordered_mapを作成し、2 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

これは、マップ内の各要素を手動で検索しようとするよりもはるかに時間がかかることがあります。いい答え。 – Vality

+2

実際には、これと受け入れられた答えは同じ時間の複雑さを持っています:O(n)。しかし、この答えは、格納された要素のいくつかの割り当てとコピーを作成します。受け入れられた答えはそうではありません、純粋に不変のデータで動作します。 – michalsrb

1

私は明白な質問をしますが、それは本当にすべて変更:unordered_mapにおける平等の概念と両立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)

であり、mapunordered_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; 
} 

はもちろん、これは少し高価です。

関連する問題