2010-04-13 3 views
2

Не используется 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. 

Я уверен, что это что-то делать с на устройство сравнения карты/пара, но не могу понять его.

ответ

5
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 элемента».

+0

Спасибо, ты прав, и я исправил код. Я перепечатал это из исходного кода на сайте клиента. Клиент имеет строгие правила по отправке кода, поэтому мне пришлось повторно войти и не обнаружил ошибку. –

6

Niki, безусловно, правильно о вашей типографии - 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, млн [3]) и (4, млн [4]), так как их ключи матч. Элементы всегда копируются из первого диапазона итераторов.

Обратите внимание, что карты всегда сортируются по типам map::value_compare, которые содержат. Если вы используете функцию funky compare, то set_intersection не будет работать без функции сравнения, явно предоставленной, если элементы карты не соответствуют порядку относительно std::less.

+0

Большое спасибо. Проблема в моем случае была ошибкой в ​​операторе <() –