unordered_multimap - повторение результата find () дает элементы с другим значением - PullRequest
14 голосов
/ 28 января 2012

Мультикарта в C ++, кажется, работает очень странно, я хотел бы знать, почему

#include <iostream>
#include <unordered_map>

using namespace std;

typedef unordered_multimap<char,int> MyMap;

int main(int argc, char **argv)
{
    MyMap map;
    map.insert(MyMap::value_type('a', 1));
    map.insert(MyMap::value_type('b', 2));
    map.insert(MyMap::value_type('c', 3));
    map.insert(MyMap::value_type('d', 4));
    map.insert(MyMap::value_type('a', 7));
    map.insert(MyMap::value_type('b', 18));

    for(auto it = map.begin(); it != map.end(); it++) {
        cout << it->first << '\t';
        cout << it->second << endl;
    }

    cout << "all values to a" << endl;
    for(auto it = map.find('a'); it != map.end(); it++) {
        cout << it->first << '\t' << it->second << endl;
    }

}

это вывод:

c   3
d   4
a   1
a   7
b   2
b   18
all values to a
a   1
a   7
b   2
b   18

почему в выводе по-прежнему есть что-то с ключом b, когда я явно запрашиваю 'a'? Это ошибка компилятора или stl?

Ответы [ 4 ]

48 голосов
/ 28 января 2012

find, как реализовано, возвращает итератор для первого элемента, который соответствует ключу в мультикарте (как с любой другой картой).Вы, вероятно, ищете equal_range:

// Finds a range containing all elements whose key is k.
// pair<iterator, iterator> equal_range(const key_type& k)
auto its = map.equal_range('a');
for (auto it = its.first; it != its.second; ++it) {
    cout << it->first << '\t' << it->second << endl;
}
9 голосов
/ 28 января 2012

Это не ошибка, это дизайн. find возвращает итератор для одного из соответствующих элементов, вот и все. Вы будете повторять до конца карты со своей конструкцией.

Вам нужно использовать multimap::equal_range, чтобы делать то, что вы хотите.

4 голосов
/ 26 марта 2016

Пример www.cplusplus.com приведен в разделе «Как использовать метод equal_range для получения всех элементов, имеющих одинаковый ключ».

// unordered_multimap::equal_range
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>

typedef std::unordered_multimap<std::string,std::string> stringmap;

int main ()
{
  stringmap myumm = {
     {"orange","FL"},
     {"strawberry","LA"},
     {"strawberry","OK"},
     {"pumpkin","NH"}
  };

  std::cout << "Entries with strawberry:";
  auto range = myumm.equal_range("strawberry");
  for_each (
    range.first,
    range.second,
    [](stringmap::value_type& x){std::cout << " " << x.second;}
  );

  return 0;
}

Пожалуйста, укажите ссылку: http://www.cplusplus.com/reference/unordered_map/unordered_multimap/equal_range/

0 голосов
/ 28 января 2012

Казалось бы, вы получаете итератор в полный «список» пар, начиная с первой пары с «а» в качестве ключа. Поэтому, когда вы выполняете итерацию до конца, естественно, вы получите все, кроме «а». Если бы вы искали «c», вы, вероятно, просматривали бы весь «список», делая то, что вы делаете там. Возможно, вам следует повторить «it! = Map.end () && it-> first == 'a'", если вы хотите получить все a.

...