Установить пересечение в C ++ по ключам карты - PullRequest
0 голосов
/ 14 мая 2019

У меня есть две карты

map<string, int> word_count1, word_count2;

Я пытаюсь найти пересечение множества между этими двумя картами.Используя метод set_intersection в std ::gorithms.

map<string, int> intersection;
set_intersection(word_count1.begin(), word_count1.end(), 
                 word_count2.begin(), word_count2.end(), 
                 inserter(intersection, intersection.begin()), 
                  [](pair<string, int> p1, pair<string, int>p2){
                           return p1.first != p2.first;
                  });

Я пробовал это без функции сравнения, с word_count1.key_comp () и вышеупомянутой лямбда-функцией сравнения.

Я точно знаю, что

  1. На обеих картах есть данные.
  2. Пересечение не пустое.

Однако, когда я проверяю значения в карте пересечений, я ничего не нахожу.

Я также пробовал это без устройства вставки, и возвращаемое значение, которое я получаю после вызова функции, указывает на то, что значений нет!Что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 14 мая 2019

Кажется, есть небольшое недоразумение относительно оператора сравнения std::set_intersection. Функция компаратора (или лямбда) должна возвращать true, если первый элемент меньше второго элемента. Следовательно, и !=, и == не возвращают надлежащий (т.е. ожидаемый) результат. Смени оператора и все работает:

std::set_intersection(word_count1.begin(), word_count1.end(),
             word_count2.begin(), word_count2.end(),
             inserter(intersection, intersection.begin()),
              [](std::pair<std::string, int> p1, std::pair<std::string, int>p2){
                       // Compare with less than operator here.
                       return p1.first < p2.first;
              });

Полный рабочий пример может быть:

#include <algorithm>
#include <iostream>
#include <map>
#include <string>

int main(int argc, char** argv)
{
  std::map<std::string, int> word_count1 = {
    { "foo", 1 },
    { "bar", 3 },
    { "baz", 5 }
  };

  std::map<std::string, int> word_count2 = {
    { "foo", 4 },
    { "qux", 2 },
    { "baz", 5 },
    { "quux", 6 }
  };


  std::map<std::string, int> intersection;
  std::set_intersection(word_count1.begin(), word_count1.end(),
      word_count2.begin(), word_count2.end(),
      inserter(intersection, intersection.begin()),
      [](std::pair<std::string, int> p1, std::pair<std::string, int>p2){
          return p1.first < p2.first;
      }
  );

  for(const auto & elem: intersection)
  {
    std::cout << elem.first << " " << elem.second << "\n";
  }
}

Выходные данные в этом случае:

baz 5
foo 1

(протестировано с GCC 7.4.0.)

2 голосов
/ 14 мая 2019

Вам нужно немного изменить лямбду. Операция сравнения operator<, а не operator==, поэтому вам нужно что-то вроде:

std::set_intersection
    (word_count1.begin(), word_count1.end(), 
     word_count2.begin(), word_count2.end(), 
     inserter (intersection, intersection.begin()),
     [](const std::pair<std::string, int> &p1, const std::pair<std::string, int> &p2)
         {return p1.first < p2.first;});

Также обратите внимание, что лучше передавать параметры в лямбду как const ref, так как это позволяет избежать ненужных копий, и что для C ++ 14 и более поздних версий лямбда может быть упрощена до:

 [](const auto &p1, const auto &p2)
     {return p1.first < p2.first;});

Живая демоверсия

...