112

Perhaps this is a duplicate but I did not find anything searching: When erase(value) is called on std::multiset all elements with the value found are deleted. The only solution I could think of is:

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

This is ok but I thought there might be better. Any Ideas ?

Martin
  • 4,738
  • 4
  • 28
  • 57

10 Answers10

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

I would imagine there is a cleaner way of accomplishing the same. But this gets the job done.

Davide Spataro
  • 7,319
  • 1
  • 24
  • 36
user2251346
  • 620
  • 5
  • 14
44

Try this one:

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

As long as you can ensure that the value exists in the set. That works.

Mooncrater
  • 4,146
  • 4
  • 33
  • 62
Strange
  • 459
  • 4
  • 6
4
 if(my_multiset.find(key)!=my_multiset.end())
   my_multiset.erase(my_multiset.equal_range(key).first);

This is the best way i can think of to remove a single instance in a multiset in c++

  • 2
    Compared to the solution i proposed in the question your code does two searches (find + equal_range) instead of one which is inefficient – Martin Aug 07 '16 at 21:50
  • as this is same complexity, I very like this answer. Thank you – Crystal Nov 12 '19 at 17:51
3

This worked for me:

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

if val exists in the multi-set.

סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
Yukty
  • 31
  • 2
  • If `val` does not exist in `multi_set`, `multi_set.find(val)` will return `multi_set.end()`. Passing and end iterator to `erase()` is undefined behavior. I wouldn't do this, even though it may work fine for some implementations. – Fauzan Aug 15 '23 at 14:52
2

I would try the following.

First call equal_range() to find the range of elements that equal to the key.

If the returned range is non-empty, then erase() a range of elements (i.e. the erase() which takes two iterators) where:

  • the first argument is the iterator to the 2nd element in the returned range (i.e. one past .first returned) and

  • the second argument as the returned range pair iterator's .second one.


Edit after reading templatetypedef's (Thanks!) comment:

If one (as opposed to all) duplicate is supposed to be removed: If the pair returned by equal_range() has at least two elements, then erase() the first element by passing the the .first of the returned pair to single iterator version of the erase():

Pseudo-code:

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

if( distance( pit.first, pit.second ) >= 2 ) {
    mymultiset.erase( pit.first );
}
Community
  • 1
  • 1
Arun
  • 19,750
  • 10
  • 51
  • 60
1

Since C++17 (see here):

mySet.extract(val);
TMueller83
  • 412
  • 3
  • 11
0

We can do something like this:

multiset<int>::iterator it, it1;
it = myset.find(value);
it1 = it;
it1++;
myset.erase (it, it1);
Dipen Dadhaniya
  • 4,550
  • 2
  • 16
  • 24
  • 1
    Overkill. "Iterator pointing to a single element to be removed from the unordered_multiset." – Andrew May 19 '18 at 20:05
0

Here is a more elegant solution using "if statement with initializer" introduced in C++17:

if(auto it = mySet.find(value); it != mySet.end())
    mySet.erase(value);

The advantage of this syntax is that the scope of the iterator it is reduced to this if statement.

Brainless
  • 1,522
  • 1
  • 16
  • 30
-1
 auto itr=ms.find(value);  
  while(*itr==value){
  ms.erase(value);
  itr=ms.find(value);  
  }

Try this one It will remove all the duplicates available in the multiset.

-2

In fact, the correct answer is:

my_multiset.erase(my_multiset.find(value));
Mike Smith
  • 527
  • 2
  • 6
  • 20