Использование карты с set_intersection
Ранее не использовал set_intersection, но я верю, что он будет работать с картами. Я написал следующий пример кода, но он не дает того, что я ожидал:
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
struct Money
{
double amount;
string currency;
bool operator< ( const Money& rhs ) const
{
if ( amount != rhs.amount )
return ( amount < rhs.amount );
return ( currency < rhs.currency );
}
};
int main( int argc, char* argv[] )
{
Money mn[] =
{
{ 2.32, "USD" },
{ 2.76, "USD" },
{ 4.30, "GBP" },
{ 1.21, "GBP" },
{ 1.37, "GBP" },
{ 6.74, "GBP" },
{ 2.55, "EUR" }
};
typedef pair< int, Money > MoneyPair;
typedef map< int, Money > MoneyMap;
MoneyMap map1;
map1.insert( MoneyPair( 1, mn[0] ) );
map1.insert( MoneyPair( 2, mn[1] ) );
map1.insert( MoneyPair( 3, mn[2] ) ); // (3)
map1.insert( MoneyPair( 4, mn[3] ) ); // (4)
MoneyMap map2;
map2.insert( MoneyPair( 3, mn[2] ) ); // (3)
map2.insert( MoneyPair( 4, mn[3] ) ); // (4)
map2.insert( MoneyPair( 5, mn[4] ) );
map2.insert( MoneyPair( 6, mn[5] ) );
map2.insert( MoneyPair( 7, mn[6] ) );
MoneyMap out;
MoneyMap::iterator out_itr( out.begin() );
set_intersection( map1.begin(), map1.end(), map2.begin(), map2.end(), inserter( out, out_itr ) );
cout << "intersection has " << out.size() << " elements." << endl;
return 0;
}
Поскольку пары с метками (3) и (4) появляются на обеих картах, я ожидал, что получу 2 элемента на пересечении, но нет, я получу:
intersection has 0 elements.
Я уверен, что это как-то связано с компаратором на карте / паре, но не могу понять.
2 ответа
MoneyMap map2;
map1.insert( MoneyPair( 3, mn[3] ) ); // (3)
map1.insert( MoneyPair( 4, mn[4] ) ); // (4)
map1.insert( MoneyPair( 5, mn[5] ) );
map1.insert( MoneyPair( 6, mn[6] ) );
map1.insert( MoneyPair( 7, mn[7] ) );
Если это не опечатка, вы просто вставляете материал в map1 вместо того, чтобы вставлять в map2. Я проверил его с исправленным кодом, и он вывел "Пересечение имеет 2 элемента".
Ники, безусловно, прав насчет твоей опечатки - map2
здесь пусто! Однако вы должны быть осторожны с чем-то другим.
Допустим, ваш код выглядел так:
MoneyMap map1;
map1.insert( MoneyPair( 1, mn[1] ) );
map1.insert( MoneyPair( 2, mn[2] ) );
map1.insert( MoneyPair( 3, mn[3] ) ); // (3)
map1.insert( MoneyPair( 4, mn[4] ) ); // (4)
MoneyMap map2;
map2.insert( MoneyPair( 3, mn[4] ) ); // (3)
map2.insert( MoneyPair( 4, mn[3] ) ); // (4)
map2.insert( MoneyPair( 5, mn[6] ) );
map2.insert( MoneyPair( 6, mn[5] ) );
map2.insert( MoneyPair( 7, mn[1] ) );
MoneyMap out;
MoneyMap::iterator out_itr( out.begin() );
set_intersection(map1.begin(), map1.end(),
map2.begin(), map2.end(),
inserter( out, out_itr ) );
Теперь, что случилось бы? Вы найдете это out
будет пустым, потому что set_intersection
использования std::less
сравнивать элементы, а элементы ваших карт - пары - таким образом (3, mn[3]) отличается от (3, mn[4]).
Другой способ сделать это, написав
set_intersection(map1.begin(), map1.end(),
map2.begin(), map2.end(),
inserter( out, out_itr ), map1.value_comp() );
Сейчас, out
будет содержать два элемента: (3, mn[3]) и (4, mn[4]), потому что их ключи совпадают. Элементы всегда копируются из первого диапазона итератора.
Обратите внимание, что карты всегда сортируются по типу map::value_compare
они содержат. Если вы используете необычную функцию сравнения, set_intersection
не будет работать без явно предоставленного функтора сравнения, если элементы карты не будут в порядке относительно std::less
,