Как написать оператор сравнения для структуры, содержащей карту?

0

У меня есть структура вроде:

   struct MyStruct
    {

    char *name;
    map<char*,char*> mymap;//assume that this map insert data in increasing order
    };

У меня есть другая карта:

    map<MyStruct,int,Compare> mTest;

    //compare function for less then operator
    struct Compare
    : public std::binary_function<MyStruct, MyStruct, bool>
    {
        bool operator()(const MyStruct &a, const MyStruct&b)
        {
            if(strcmp(a.name,b.name)< 0)
                return true;
            else if(strcmp(a.name,b.name)==0)
            {
                //How should I compare map 'mymap' ??
            }
            return false;
        }
    }

Итак, как мне написать сравнение для mymap?

Это то, что я хочу:

Две карты равны, если

  1. там имя равно

  2. Размер их карт равен

  3. то содержание карты должно быть равным, т.е. как их ключ, так и ценность.

  • 0
    Вы должны использовать синтаксис C ++, прежде всего. elseif является C ++, а ваш if отсутствует закрывающим пареном. Тогда это полностью зависит от того, как бы вы правильно отсортировали две карты. Тебе решать. Единственное, что вы должны убедиться, что это строгий порядок.
  • 0
    @ArneMertz Я обновил код выше. Предположим, что mymap хранит данные в порядке возрастания. Теперь, как я могу сравнить две карты в функции Compare ?
Показать ещё 7 комментариев
Теги:
map

2 ответа

1
Лучший ответ

Есть несколько способов заказывать карты. Необходимо учитывать три вещи: размер карт, ключи и значения. Так как сама карта, упорядоченная уже ключами, естественно сравнивать значения после ключей. Поэтому, учитывая две карты одинакового размера, важны только ключи. Я буду использовать целые ключи и значения для более простого примера:

 map1: 1->42       map2: 5->16     map3: 1->44   map4: 1->42
       2-> 5             6->16           2->67         2-> 7
       7-> 8             7-> 8           3->10         7-> 8

Теперь сравнить map1 и map2 легко: первый ключ map1 ниже первого ключа map2, поэтому map1 должен быть первым.
Сравнение map1 и map3 дает тот же ключ в первой записи, но соответствующее значение ниже для map1, поэтому map1 снова появляется первым.
Сравнение map1 и map4 показывает, что первая пара ключ-значение полностью совпадает, но сравнение второй пары показывает, что map1 приходит первым, потому что его значение снова становится ниже.

Порядок по размеру снова тривиален. Карта с меньшим размером доходит до одного с большим размером.

Теперь это полностью зависит от вас, если вы хотите сначала отсортировать по размеру или по ключевым словам/значениям. Рассмотрим дополнительную карту:

map5: 5->16
      7-> 3

Размер map5 равен 2, размер map1 равен 3. Поэтому, если вы сначала закажете по размеру, map5 появится перед map1. Если сначала сравнить элементы, map1 приходит перед map5, потому что первый элемент ниже.

Это сравнение уже доступно в C++: std::pair предоставляет operator< который сначала сравнивает ключи и значения. Поэтапное сравнение набора элементов в целом выполняется vía std::lexicographical_compare. Кроме того, std::map предоставляет operator< который выполняет лексикографическое сравнение для вас. Он сначала сравнивает элементы, а второй.

Однако в вашем случае, поскольку вы используете char* вместо string C++, вам нужно написать собственный компаратор для pair<char*, char*> которые являются элементами вашей карты. Я бы советовал использовать строки alltogether, это становится очень простым, потому что std::string предоставляет operator<:

struct MyStruct
{
  string name;
  map<string, string> mymap;
};


map<MyStruct,int,Compare> mTest;

//compare function for less then operator
struct Compare
{
  bool operator()(const MyStruct &a, const MyStruct&b)
  {
    return a.name < b.name //name first
      || (a.name == b.name && cmp(a.mymap, b.mymap));
  }

  bool cmp(map<string, string> const& lhs, map<string, string> const& rhs)
  {
    return lhs.size() < rhs.size() //size first
      || (lhs.size() == rhs.size() && lhs < rhs); 
  }
};
1

Ваше использование char* откровенно ужасно и устарело. Используйте std::string, ваш класс станет:

struct MyStruct
{
  std::string name;
  map<std::string, std::string> mymap;
};

Теперь для карты вам необходимо предоставить оператора меньше, например:

struct MyStruct
{
  std::string name;
  map<std::string, std::string> mymap;

  friend bool operator<(MyStruct const& lhs, MyStruct const& rhs)
  {
    // Now the comparison is easier - use the defaults!
    if (lhs.name < rhs.name)
      return true;
    return lhs.mymap < rhs.mymap; // this does a lexicographical comparison of all values.
  }
};

Тогда ваша карта структур станет:

std::map<MyStruct, int> mTest;

Нет необходимости в громоздком коде.

EDIT: только что заметили ваше обновление, вы можете реализовать другие операторы для MyStruct и составить их, как я сделал выше, от вызова логических операторов name и mymap, вам не нужно самостоятельно внедрять какие-либо пользовательские хаки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню