Как избежать дублирования пар / найти пару в multimap?

У меня есть (рабочий) код, который использует multimap<string,string>. Я хотел бы изменить его, чтобы запретить дубликаты значений на одном ключе (очевидно, разные значения на одном ключе в порядке, иначе я бы не использовал multimap).

удивительно, что тип не кажется иметь встроенный способ избежать дубликатов или найти пару ключ-значение (только чтобы найти ключ). Но я полагаю, что у кого-то на SO должен быть готовый обходной путь. Кто?

4 ответов


std::map<std::string, std::set<std::string>> казалось бы, именно те свойства, которые вы ищете (хотя и уступает сложности unordered_map и unordered_set).


вот что я придумал:

template<class K, class V>
typename multimap<K, V>::const_iterator find_pair(const multimap<K, V>& map, const pair<K, V>& pair)
{
    typedef multimap<K, V>::const_iterator it;
    std::pair<it,it> range = map.equal_range(pair.first);
    for (it p = range.first; p != range.second; ++p)
        if (p->second == pair.second)
            return p;
    return map.end();
}
template<class K, class V>
bool insert_if_not_present(multimap<K, V>& map, const pair<K, V>& pair)
{
    if (find_pair(map, pair) == map.end()) {
        map.insert(pair);
        return true;
    }
    return false;
}

(Это не эффективно, когда есть большое количество значений, подключенных к одному ключу, но в моем случае есть несколько значений для каждого ключа.)


мое предложение вам было бы обернуть multimap в класс и просто выполнить проверку в методе, где вы добавляете что-то в карту. Остальные функции просто перейдут к методам multimap. Это делает много кода котельной плиты, но если вам когда-либо понадобится сделать другие типы проверок, это будет проще.


Кажется,

      std::set<std::pair<std::string,std::string>>>

будет иметь именно те свойства, которые вы ищете.

однако это не карта и не multimap. Вы можете сохранить как multimap, так и набор пар ключей, значений или создать этот набор только для проверки согласованности.

Я бы использовал этот набор и создал адаптер над ним для интерфейса multimap. Возможно, это не самое простое решение для реализации, но с лучшей эффективностью работы.

см. " шаблон дизайна адаптера" вопросы для справок.


[обновление]

посмотреть мои пример работающего в качестве отправной точки.

Е. Г. как перебрать все значения ключа - см.:

typedef  std::set<std::pair<std::string, std::string> > ssset;

ssset::iterator get_key(ssset& s, std::string key)
{
  ssset::iterator it = s.lower_bound(std::make_pair(key, ""));
  if (it != s.end() && it->first == key) return it;
  return s.end();   
}

for (ssset::iterator it = get_key(s, "abc"); it != s.end() && it->first == "abc"; ++it)
   std::cout << it->first << "->" << it->second << std::endl;