In std :: multiset gibt es eine Funktion oder einen Algorithmus, um nur ein Sample (unicate oder duplicate) zu löschen, wenn ein Element gefunden wird

83

Vielleicht ist dies ein Duplikat, aber ich habe keine Suche gefunden: Wenn erase(value)aufgerufen wird, werden std::multisetalle Elemente mit dem gefundenen Wert gelöscht. Die einzige Lösung, an die ich denken könnte, ist:

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

Das ist in Ordnung, aber ich dachte, es könnte besser sein. Irgendwelche Ideen ?

Martin
quelle
22
Dies ist ein durchaus vernünftiger Ansatz.
Templatetypedef
Stellt dieser Ansatz sicher, dass der angegebene Schlüssel ("5") doppelt vorhanden ist?
Arun
@ArunSaha: Nein. Aber wenn es kein Duplikat ist, möchte ich es trotzdem löschen. Durch die Antworten habe ich das Gefühl, dass es keine bessere Lösung gibt. Vielleicht war die Frage überhaupt dumm :-P
Martin
1
Für multimap: Gibt es eine Garantie dafür, welche Elemente findzurückgegeben werden? (Reihenfolge der Einfügung? Auch nach einer solchen Löschung? Implementierung abhängig?)
P Marecki
2
Ehrlich gesagt ist es eine so offensichtliche Gefahr bei der Verwendung von Multisets, die nicht zu den am häufigsten verwendeten Klassen gehören.
Predelnik

Antworten:

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

Ich würde mir vorstellen, dass es einen saubereren Weg gibt, dasselbe zu erreichen. Aber das erledigt den Job.

user2251346
quelle
7
Dies unterscheidet sich nicht von dem, was in Frage kommt.
Troubadour
1
Genau! Macht keinen Sinn. 12 andere Leute haben etwas Nützliches in der Antwort gesehen, also weiß ich, dass ich nicht verrückt werde.
user2251346
6
Übersehen Sie niemals die Möglichkeit, dass Sie zusammen mit allen anderen verrückt werden :)
Apollys unterstützt Monica
15

Probier diese:

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

Solange Sie sicherstellen können, dass die valueAusgänge im Set. Das funktioniert.

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

Dies ist der beste Weg, den ich mir vorstellen kann, um eine einzelne Instanz in einem Multiset in C ++ zu entfernen

varun kunchakuri
quelle
1
Im Vergleich zu der Lösung, die ich in der Frage vorgeschlagen habe, führt Ihr Code zwei Suchvorgänge (find + same_range) anstelle einer ineffizienten durch
Martin
Da dies dieselbe Komplexität ist, gefällt mir diese Antwort sehr gut. Vielen Dank
Crystal
1

Ich würde folgendes versuchen.

Rufen Sie zuerst equal_range()auf, um den Bereich der Elemente zu ermitteln, die dem Schlüssel entsprechen.

Wenn der zurückgegebene Bereich nicht leer ist, dann erase()ein Bereich von Elementen (dh der, erase()der zwei Iteratoren benötigt), wobei:

  • Das erste Argument ist der Iterator für das zweite Element im zurückgegebenen Bereich (dh eine zurückgegebene Vergangenheit .first) und

  • das zweite Argument als das des zurückgegebenen Bereichspaar-Iterators .second.


Nach dem Lesen des Kommentars von templatetypedef (Danke!) Bearbeiten :

Wenn ein (im Gegensatz zu allen) Duplikat entfernt werden soll: Wenn das von zurückgegebene Paar equal_range()mindestens zwei Elemente enthält, erase()übergibt das erste Element das erste des zurückgegebenen Paares an eine einzelne Iteratorversion von erase():

Pseudocode:

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

if( distance( pit.first, pit.second ) >= 2 ) {
    mymultiset.erase( pit.first );
}
Arun
quelle
2
Ich denke, die Frage ist, nur ein Duplikat zu entfernen, nicht alle Duplikate.
Templatetypedef
Haben Sie eine Idee, ob dies schneller ist als meine Lösung und wenn ja, warum?
Martin
1

Das hat bei mir funktioniert:

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

wenn val im Multi-Set vorhanden ist.

Yukty
quelle
0

Wir können so etwas tun:

multiset<int>::iterator it, it1;
it = myset.find(value);
it1 = it;
it1++;
myset.erase (it, it1);
Dipen Dadhaniya
quelle
1
Overkill. "Iterator zeigt auf ein einzelnes Element, das aus dem unordered_multiset entfernt werden soll."
Andrew
-3

In der Tat ist die richtige Antwort:

my_multiset.erase(my_multiset.find(value));
user3075328
quelle
1
Wenn im Multiset kein Wert vorhanden ist, führt dies zu undefiniertem Verhalten .
kien_coi_1997