ошибка сравнения равенства двух std ::unordered_map

#c

#c

Вопрос:

Как проверить равенство двух std::unordered_map , используя std::equal для проверки, имеют ли оба контейнера одинаковые ключи и соответствующие им значения ключей. Ниже мой код печатается unequal , даже если оба контейнера имеют одинаковый размер, набор ключей и соответствующие значения ключей равны.

 #include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<char, int> um1, um2;
    um1['f'] = 1;
    um1['o'] = 1;
    um1['r'] = 1;

    um2['o'] = 1;
    um2['r'] = 1;
    um2['f'] = 1;

    if (um1.size() == um2.size() amp;amp; std::equal(um1.begin(), um1.end(), um2.begin()))
        std::cout << "equal" << std::endl;
    else
        std::cout << "unequal" << std::endl;
}
 

Комментарии:

1. If (um1 == um2) ?

2. имейте в виду, что это неупорядоченная карта, поэтому порядок, в котором итераторы будут перебирать ключи, не указан и может казаться случайным. Это будет работать с a std::map , поскольку оно будет сортировать свои элементы согласованным образом. Но std::unordered_map реализован как hashmap, поэтому порядок, в котором вы получите элементы, зависит от хэш-функции, размера корзины и порядка вставки. (это также может измениться в дальнейшем, если произойдет перефразирование)

3. Обратитесь к этому — cplusplus.com/reference/unordered_map/unordered_map/operators

4. @NathanOliver это дает мне требуемый результат. Работает ли это для любого порядка вставки?

5. @Harry operator== будет работать для любого порядка вставки. однако имейте в виду, что сравнение двух unordered_maps может быть намного дороже, чем сравнение двух карт нормалей (из-за их несортированного характера) — сравнение std::map s будет не более O(n) , в то время как сравнение std::unsorted_map s может быть до O(n²) . (где n — количество элементов в карте)

Ответ №1:

https://en.cppreference.com/w/cpp/algorithm/equal

Два диапазона считаются равными, если они имеют одинаковое количество элементов и для каждого итератора i в диапазоне [first1,last1), *i равно *(first2 (i — first1)).

Считайте, что этот код добавлен в ваш фрагмент кода:

 for (auto it : um1)
    std::cout << it.first << ": " << it.second << std::endl;
std::cout << std::endl;
for (auto it : um2)
    std::cout << it.first << ": " << it.second << std::endl;
 

f: 1
o: 1
r: 1

o: 1
r: 1
f: 1

Обратите внимание, что итерация выполняется в другом порядке, как и следовало ожидать. Поэтому они не являются std::equal, потому что (как описано выше), который ожидает одинаковые значения в том же порядке.

Однако этот конкретный контейнер имеет свой собственный operator==, как указано в комментариях, который проверяет равенство значений, как вы изначально ожидали для этого конкретного контейнера.