В std :: multiset есть функция или алгоритм для удаления только одного образца (однозначного или повторяющегося), если элемент найден

83

Возможно, это дубликат, но я ничего не нашел поиском: При erase(value)вызове std::multisetвсе элементы с найденным значением удаляются. Единственное решение, которое я мог придумать, это:

std::multiset<int>::iterator hit(mySet.find(5));
if (hit!= mySet.end()) mySet.erase(hit);

Это нормально, но я подумал, что может быть лучше. Есть идеи ?

Мартин
источник
22
Это вполне разумный подход.
templatetypedef
Гарантирует ли этот подход дублирование данного ключа («5»)?
Арун,
@ArunSaha: Нет. Но если это не дубликат, я все равно хочу его удалить. Судя по полученным ответам, я чувствую, что лучшего решения нет. Может быть, вопрос изначально был дурацким :-P
Мартин
1
Для multimap: есть ли гарантия, какие элементы findвозвращаются? (Порядок вставки? Даже после такого стирания? Зависит от реализации?)
P Marecki
2
Честно говоря, это такая неочевидная ошибка при использовании мультимножества, которое не входит в число наиболее часто используемых классов.
Пределник

Ответы:

31
auto itr = my_multiset.find(value);
if(itr!=my_multiset.end()){
    my_multiset.erase(itr);
}

Я полагаю, что есть более чистый способ сделать то же самое. Но это делает свою работу.

user2251346
источник
10
Это не отличается от того, о чем идет речь.
Трубадур
2
Я согласен! В этом нет никакого смысла. Еще 12 человек увидели в ответе что-то полезное, поэтому я знаю, что не сойду с ума.
user2251346 04
8
Никогда не
упускайте
16

Попробуй это:

multiset<int> s;
s.erase(s.lower_bound(value));

Пока вы можете убедиться, что valueвыходы в комплекте. Это работает.

Странный
источник
2
 if(my_multiset.find(key)!=my_multiset.end())
   my_multiset.erase(my_multiset.equal_range(key).first);

Это лучший способ, который я могу придумать, чтобы удалить один экземпляр в мультимножестве в c ++

варун кунчакури
источник
1
По сравнению с решением, которое я предложил в вопросе, ваш код выполняет два поиска (find + equal_range) вместо одного, который неэффективен
Мартин
так как это такая же сложность, мне очень нравится этот ответ. Спасибо
Crystal
1

Я бы попробовал следующее.

Сначала вызовите, equal_range()чтобы найти диапазон элементов, равных ключу.

Если возвращаемый диапазон непустой, тогда erase()диапазон элементов (то есть, erase()который принимает два итератора), где:

  • первый аргумент - это итератор для 2-го элемента в возвращаемом диапазоне (т.е. .firstвозвращенный один прошлый ) и

  • второй аргумент как итератор возвращаемой пары диапазонов .second.


Отредактируйте после прочтения комментария templatetypedef (спасибо!):

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

Псевдокод:

pair<iterator, iterator> pit = mymultiset.equal_range( key );

if( distance( pit.first, pit.second ) >= 2 ) {
    mymultiset.erase( pit.first );
}
Арун
источник
2
Я думаю, что вопрос заключается в том, чтобы удалить только один дубликат, а не все дубликаты.
templatetypedef
Есть идеи, быстрее ли это моего решения, и если да, то почему?
Мартин
1

Это сработало для меня:

multi_set.erase(multi_set.find(val));

если val существует в мультинаборе.

Юкты
источник
0

Мы можем сделать что-то вроде этого:

multiset<int>::iterator it, it1;
it = myset.find(value);
it1 = it;
it1++;
myset.erase (it, it1);
Дипен Дадхания
источник
1
Перебор. «Итератор, указывающий на единственный элемент, который нужно удалить из unordered_multiset.»
Эндрю
0
 auto itr=ms.find(value);  
  while(*itr==value){
  ms.erase(value);
  itr=ms.find(value);  
  }

Попробуйте этот. Он удалит все дубликаты, доступные в мультимножестве.

Аннкит Сингх
источник
-3

На самом деле правильный ответ:

my_multiset.erase(my_multiset.find(value));
user3075328
источник
1
Если значение не существует в мультимножестве, это вызывает неопределенное поведение .
kien_coi_1997