Как узнать, имеют ли два `std :: multimap`s одинаковое содержимое? - PullRequest
0 голосов
/ 11 декабря 2018

Должен признать, что я никогда не изучал стандартную библиотеку должным образом, но это застало меня врасплох

#include <iostream>
#include <map>

int main (int argc, char ** argv)
{
    std::multimap<int, int> mm1;
    mm1.insert( std::pair<int, int>(0, 0) );
    mm1.insert( std::pair<int, int>(0, 1) );

    std::multimap<int, int> mm2;
    mm2.insert( std::pair<int, int>(0, 1) );
    mm2.insert( std::pair<int, int>(0, 0) );

    std::cout << "The maps are "
          << ( (mm1 == mm2) ? "equal" : "not equal" )
          << std::endl;
}

И, попробовав это, мы получили ...

$ g++ --std=c++11 -o multimaporder multimaporder.cc
$ ./multimaporder 
The maps are not equal

Итак, порядок размещения вещей на карте имеет значение.Это не было бы моим первым ожиданием для ассоциативного контейнера, но хорошо.

С контейнером с произвольным доступом мой следующий план, как правило, состоял бы в том, чтобы отсортировать их и затем сравнить ... но добавив

#include <algorithm>
//...
    std::sort( mm1.begin(), mm1.end() );
    std::sort( mm2.begin(), mm2.end() );

    std::cout << "The *sorted* maps are "
              << ( (mm1 == mm2) ? "equal" : "not equal" )
              << std::endl;

просто результаты - это множество жалоб на то, что не удалось найти приемлемый набор итераторов для sort.

Так что же это правильный способ выяснить, если два multimap имеют одинаковое содержимое

Ответы [ 3 ]

0 голосов
/ 11 декабря 2018

Итак, порядок размещения объектов на карте имеет значение.

Нет, для карты это не имеет значения, но вы используете multimap, который является другим зверем.Как указано в документации для std::multimap::insert()

1-2) вводится значение. Если в контейнере есть элементы с эквивалентным ключом, вставляется верхняя граница этого диапазона. (Начиная с C ++ 11) Перегрузка (2) эквивалентна emplace (std :: forward

(value))) и участвует только в разрешении перегрузки, если std :: is_constructible :: value == true.

выделение мое.Возможные решения:

  • вставьте значения в std::multimap, чтобы они оставались в одном и том же порядке в обоих контейнерах (например, отсортированными), путем предоставления правильной подсказки для std::multimap::insert.
  • useконтейнер, в котором все пары полностью отсортированы, например std::set<std::pair<int,int>>, вы должны знать о различиях в поведении
  • использовать специальный компаратор, который каким-то образом реализует, если значения в другом порядке равны

Примечаниевы не можете прибегнуть к элементам в std::multimap, передав их итераторы в std::sort, что нарушит инвариант контейнера.

0 голосов
/ 12 декабря 2018

Для этого случая вам нужно сравнить наборы, как показано ниже

bool comp ()
{
    using Map = std::multimap<int, int>;
    Map mm1;
    mm1.insert( std::pair<int, int>(0, 0) );
    mm1.insert( std::pair<int, int>(0, 1) );

    Map mm2;
    mm2.insert( std::pair<int, int>(0, 1) );
    mm2.insert( std::pair<int, int>(0, 0) );


    return std::set<Map::value_type>(mm1.begin(), mm1.end()) == std::set<Map::value_type>(mm2.begin(), mm2.end());
}
0 голосов
/ 11 декабря 2018

Per [associative.reqmts] / 4 std::multimap требует, чтобы порядок вставки для эквивалентных ключей сохранялся, поэтому два контейнера будут сравниваться равными, только если они имеют одинаковые значения в одном и том же порядке.

Если вы не заботитесь о заказе, вы можете использовать std::unordered_multimap, который не заботится о заказе и будет сравниваться равным, если они имеют одинаковые значения

int main (int argc, char ** argv)
{
    std::unordered_multimap<int, int> mm1;
    mm1.insert( std::pair<int, int>(0, 0) );
    mm1.insert( std::pair<int, int>(0, 1) );

    std::unordered_multimap<int, int> mm2;
    mm2.insert( std::pair<int, int>(0, 1) );
    mm2.insert( std::pair<int, int>(0, 0) );

    std::cout << "The maps are "
          << ( (mm1 == mm2) ? "equal" : "not equal" )
          << std::endl;
}

Выходы

The maps are equal
...