Удалите только один элемент из мультикарты с повторяющимися ключами

У меня есть мульти-карта с объектами Note, из которых я хочу удалить только один объект. Может быть несколько объектов Note с одним и тем же ключом. Проблема в том, что прямо сейчас удаляются также объекты, которые не входят в указанный мной диапазон ключей:

long key = note.measureNumber * 1000000 + note.startTime; // = 2000001
multimap<long, Note>::iterator it;
for (it = noteList.lower_bound(key); it != noteList.end() && it->first < (key + 1); it++) {
    if(it->second.frequency == note.frequency){
        noteList.erase(it);
    }
}

Когда я запускаю этот код с ключом 2000001 объект, я могу стереть нужный объект, но другой объект с ключом 1000017 также удаляется. Однако оба объекта имеют одинаковую частоту.

Есть идеи, что не так с моим циклом for?

РЕДАКТИРОВАТЬ: Для ясности, я хочу проверять только объекты с одним конкретным ключом (в данном случае 2000001), итератору нет необходимости просматривать объекты с разными ключами, кроме этого.


person Community    schedule 21.08.2012    source источник


Ответы (3)


Как только вы удалите итератор, он станет недействительным. Если вы хотите стереть карту во время итерации по ней, ваш код необходимо изменить. Попробуй это:

multimap<long, Note>::iterator it;
for (it = noteList.lower_bound(key); it != noteList.end() && it->first < (key + 1);) {
    if(it->second.frequency == note.frequency){
        noteList.erase(it++);
    }
    else
    {
        ++it;
    }
}
person Craig H    schedule 21.08.2012
comment
На самом деле каждый раз нужно стирать только один элемент. Любая идея, как я могу просто выйти из цикла for, когда элемент был удален? - person ; 22.08.2012
comment
Поставьте 'разрыв' после стираемой линии - person Rob Walker; 22.08.2012
comment
Я попробую это. Я действительно думал, что это поможет избежать условия if - person ; 22.08.2012

Вызов erase () с итератором сделает его недействительным, поэтому вы не сможете продолжать его использовать.

См. Можно Я продолжаю использовать итератор после того, как элемент был удален из std :: multimap ‹>

person Rob Walker    schedule 21.08.2012

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

for (it = noteList.lower_bound(key); it != noteList.upper_bound(key) && it->first == key; it++)
{
    if(it->second.frequency == note.frequency)
    {
       noteList.erase(it++);
    }
    else
    {
        ++it;
    }
}
person Alex I.    schedule 21.08.2012
comment
Но будет ли это иметь значение? как только 'it- ›first == key;' соблюдается, петля все равно остановится, не так ли? - person ; 22.08.2012