индексирование — C ++ находит и стирает элемент мультикарты

Мне нужно добавить, сохранить и удалить несколько пар объектов, например, PersonHobby, Любой человек может иметь несколько хобби, и несколько человек могут иметь одно и то же хобби. Итак, multimap — это хороший контейнер, верно?

Прежде чем добавить пару, мне нужно знать, если она еще не добавлена. Как я вижу Вот нет никакого стандартного метода класса, чтобы знать, конкретна ли пара, например. Peter-Football существует в ММ. Таким образом, я написал метод, который возвращает положительное целое число (равное расстоянию между mm.begin () и итератором пары), если пара существует и -1 иначе.

Затем мне нужно удалить пару. Я звоню своему find метод, который возвращает некоторое положительное целое число. Я звоню myMultiMap.erase(pairIndex); но пара не удаляется по какой-то причине. Это моя проблема. Очевидно, что erase метод нуждается в iterator, не int, Вопрос в том, как преобразовать целое число в итератор?

Спасибо!

ОБНОВИТЬ:
Я пробовал это c.begin() + int_value но получил ошибку error: no match for ‘operator+’ на этой линии ….

1

Решение

Не то чтобы я одобряю твой подход, но если int это расстояние между begin() и рассматриваемый итератор, вы можете просто использовать

c.begin() + int_value

или же

std::advance(c.begin(), int_value)

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

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

Есть много возможных интерфейсов, которые решают это так или иначе. То, что я бы назвал «старым способом C», будет возвращаться параметром out:

bool find_stuff(stuff, container::iterator* out_iter) {
...
if(found && out_iter)
*out_iter = found_iter;
return found;
}

используй это:

container::iterator the_iter;
if(find_stuff(the_stuff, &the_iter)) ...

или же

if(find_stuff(the_stuff, 0)) // if you don't need the iterator

Это не идиоматический C ++, но Линус был бы доволен этим.

Вторая возможная и теоретически обоснованная версия использует что-то вроде boost::optional вернуть значение. Таким образом, вы возвращаете либо некоторое значение, либо ни одного.

boost::optional<container::iterator> find_stuff(stuff) {
...
if(found && out_iter)
return found_iter;
return boost::none;
}

Использование:

boost::optional<container::iterator> found = find_stuff(the_stuff);
if(found) {
do something with *found, which is the iterator.
}

или же

if(find_stuff(the_stuff)) ...

Третье возможное решение будет идти std::set::insert способ, т.е. возвращает пару, состоящую из флага и значения:

std::pair<bool, container::iterator> find_stuff(stuff) {
...
return std::make_pair(found, found_iter);
}

Использование:

std::pair<bool, container::iterator> found = find_stuff(the_stuff);
if(found.first) ...
3

Другие решения

Подумайте, чтобы изменить свой mulitmap<Person,Hoobby> в set<pair<Person,Hobby> > — тогда у вас не будет проблем у вас сейчас. Или подумайте, чтобы изменить map<Person, set<Hobby> >, Оба варианта не позволят вставить дубликаты пар.

2

Используйте 2 набора (не несколько наборов), один для хобби и один для людей, эти два действуют как фильтры, чтобы вы не добавляли одного и того же человека дважды (или хобби). Операции вставки в этих наборах дают итератор для вставляемого элемента (или «правильный» итератор для элемента, если он уже был вставлен). Два итератора, которые вы получаете от вставки в hobbies_set и person_set, теперь используются в качестве ключа и значения в мультикарте.

Использование третьего набора (не multi_set) для отношения вместо multi_map может дать преимущество в том, что нет необходимости проверять перед вставкой отношения, если оно уже есть, оно не будет добавлено снова, а если его нет, оно будет добавлено , В обоих случаях он возвращает итератор и bool (сообщает, был ли он уже там или был добавлен)

datastructures:

typedef std::set<Hobbie> Hobbies;
typedef std::set<Person> Persons;
typedef std::pair<Hobbies::iterator,bool> HobbiesInsertRes;
typedef std::pair<Persons::iterator,bool> PersonsInsertRes;
struct Relation {
Hobbies::iterator hobbieIter;
Persons::iterator personIter;
// needed operator<(left for the as an exercies for the reader);
};
typedef set<Relation> Relations;

Hobbies hobbies;
Persons persons;
Relations relations;

вставить:

HobbiesInsertRes hres = hobbies.insert(Hobbie("foo"));
PersonsInsertRes pres = persons.insert(Person("bar"));
relations.insert(Relation(hres.first, pres.first));
// adds the relation if does not exists, if it allready did exist, well you only paid the same amount of time that you would have if you would to do a check first.

уважать:

// for a concrete Person-Hobbie lookup use
relations.find(Relation(Hobbie("foo"),Person("Bar")));

// to find all Hobbies of Person X you will need to do some work.
// the easy way, iterate all elements of relations
std::vector<Hobbie> hobbiesOfX;
Persons::iterator personX = persons.find(Person("bar"));
std::for_each(relations.begin(), relations.end(), [&hobbiesOfBar, personX](Relation r){
if(r.personIter = personX)
hobbiesOfX.push_back(r.hobbieIter);
});

// other way to lookup all hobbies of person X
Persons::iterator personX = persons.find(Person("bar"));
relations.lower_bound(Relation(personX,Hobbies.begin());
relations.upper_bound(Relation(personX,Hobbies.end());
// this needs operator< on Relation to be implemented in a way that does ordering on Person first, Hobbie second.
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector