W std :: multiset jest funkcja lub algorytm do usuwania tylko jednej próbki (unicate lub duplikat), jeśli element zostanie znaleziony


82

Być może jest to duplikat, ale nie znalazłem niczego szukającego: kiedy erase(value)jest wywoływany, std::multisetwszystkie elementy ze znalezioną wartością są usuwane. Jedyne rozwiązanie, jakie przychodzi mi do głowy, to:

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

To jest w porządku, ale pomyślałem, że może być lepiej. Jakieś pomysły ?


22
To całkiem rozsądne podejście.
templatetypedef

Czy to podejście gwarantuje, że dany klucz („5”) jest zduplikowany?
Arun

@ArunSaha: Nie. Ale jeśli to nie jest duplikat, i tak chcę go usunąć. Z odpowiedzi, które otrzymałem, mam wrażenie, że nie ma lepszego rozwiązania. Może pytanie było przede wszystkim głupie :-P
Martin

1
Do multimap: czy jest jakaś gwarancja, które elementy zostaną findzwrócone? (Kolejność wstawiania? Nawet po takim skasowaniu? Realizacja zależna?)
P Marecki

2
Szczerze mówiąc, to taka nieoczywista pułapka przy korzystaniu z multisetu, który nie należy do najczęściej używanych klas.
Predelnik

Odpowiedzi:


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

Wyobrażam sobie, że istnieje czystszy sposób osiągnięcia tego samego. Ale to wykonuje swoją pracę.


8
Nie różni się to od tego, o czym mowa.
Troubadour

1
Zgadzam się! To nie ma sensu. 12 innych osób zobaczyło coś pożytecznego w odpowiedzi, więc wiem, że nie wariuję.
user2251346

6
Nigdy nie zapominaj o możliwości, że oszalejesz razem ze wszystkimi :)
Apollys wspiera Monikę

16

Spróbuj tego:

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

Tak długo, jak możesz zapewnić, że valuewyjdzie w zestawie. To działa.


2
 if(my_multiset.find(key)!=my_multiset.end())
   my_multiset.erase(my_multiset.equal_range(key).first);

To najlepszy sposób, w jaki mogę wymyślić, aby usunąć pojedyncze wystąpienie z zestawu wielu w c ++


1
W porównaniu z rozwiązaniem, które zaproponowałem w pytaniu, twój kod wykonuje dwa wyszukiwania (znajdź + równy_zakres) zamiast jednego, które jest nieefektywne
Martin

ponieważ jest to ta sama złożoność, bardzo podoba mi się ta odpowiedź. Dziękuję
Crystal

1

Spróbowałbym następujących.

Pierwsze wywołanie, equal_range()aby znaleźć zakres elementów równy kluczowi.

Jeśli zwrócony zakres nie jest pusty, to erase()zakres elementów (tj. Ten, erase()który przyjmuje dwie iteratory), gdzie:

  • pierwszy argument to iterator do drugiego elementu w zwróconym zakresie (tj. .firstzwrócona jedna przeszłość ) i

  • drugi argument jako iterator zwracanej pary zakresów .second.


Edytuj po przeczytaniu komentarza templatetypedef (dzięki!):

Jeśli jeden (w przeciwieństwie do wszystkich) duplikatów ma zostać usunięty: Jeśli para zwrócona przez equal_range()ma co najmniej dwa elementy, to erase()pierwszy element, przekazując .first zwróconej pary do wersji z pojedynczym iteratorem erase():

Pseudo kod:

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

if( distance( pit.first, pit.second ) >= 2 ) {
    mymultiset.erase( pit.first );
}

2
Myślę, że chodzi o wyeliminowanie tylko jednego duplikatu, a nie wszystkich duplikatów.
templatetypedef

Masz pomysł, czy to jest szybsze od mojego rozwiązania, a jeśli tak, to dlaczego?
Martin,

1

To zadziałało dla mnie:

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

jeśli val istnieje w zestawie wielokrotnym.


0

Możemy zrobić coś takiego:

multiset<int>::iterator it, it1;
it = myset.find(value);
it1 = it;
it1++;
myset.erase (it, it1);

1
Przesada. „Iterator wskazujący na pojedynczy element do usunięcia z unordered_multiset.”
Andrew

0
 auto itr=ms.find(value);  
  while(*itr==value){
  ms.erase(value);
  itr=ms.find(value);  
  }

Wypróbuj ten Spowoduje to usunięcie wszystkich duplikatów dostępnych w zestawie wielokrotnym.


-3

W rzeczywistości prawidłowa odpowiedź to:

my_multiset.erase(my_multiset.find(value));

1
Jeśli wartość nie istnieje w zestawie wielokrotnym, powoduje to niezdefiniowane zachowanie .
kien_coi_1997
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.