std :: multisetには、要素が見つかった場合に1つのサンプル(一意または複製)のみを消去する関数またはアルゴリズムがあります


83

おそらくこれは重複していますが、検索するものは何も見つかりませんでした。見つかった値を持つすべての要素でerase(value)が呼び出されるstd::multisetと、削除されます。私が考えることができる唯一の解決策は次のとおりです。

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

これは大丈夫ですが、もっと良いかもしれないと思いました。何か案は ?


22
これは完全に合理的なアプローチです。
templatetypedef

このアプローチにより、指定されたキー( "5")が重複することが保証されますか?
アルン2012

@ArunSaha:いいえ。でも、重複していない場合は、とにかく削除したいと思います。私が得た答えから、私はこれ以上の解決策はないと感じています。そもそも質問はばかげていたのかもしれません:-P–
Martin

1
の場合multimap:どの要素findが返されるかについての保証はありますか?(挿入の順序?そのような消去の後でも?実装に依存しますか?)
P Marecki 2013

2
正直なところ、最も頻繁に使用されるクラスの1つではないマルチセットを使用している場合、これは明らかな落とし穴です。
Predelnik 2017年

回答:


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

同じことを達成するためのよりクリーンな方法があると思います。しかし、これで仕事は終わります。


7
これは問題の内容と同じです。
トルバドゥール

1
同意する!意味がありません。他の12人が答えに役立つものを見たので、私は夢中にならないことを知っています。
user2251346 2018

6
あなたが他のみんなと一緒に夢中になっている可能性を決して見逃さないでください:)
Apollysは

15

これを試してください:

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
私が質問で提案した解決策と比較して、あなたのコードは非効率的なものの代わりに2つの検索(find + equal_range)を行います
Martin

これは同じ複雑さなので、私はこの答えがとても好きです。ありがとう
クリスタル

1

私は以下を試してみます。

最初に呼び出しequal_range()て、キーに等しい要素の範囲を見つけます。

返される範囲が空でない場合、erase()要素の範囲(つまり、erase()2つのイテレーターを必要とする)は次のようになります。

  • 最初の引数は、返された範囲の2番目の要素(つまり、1つ過去が.first返された)へのイテレータであり、

  • 返される範囲ペアイテレータの2番目の引数.second


templatetypedefの(ありがとう!)コメントを読んだ後に編集してください

(すべてではなく)1つの重複が削除されることになっている場合:によって返されるペアにequal_range()少なくとも2つの要素がある場合、返されたペアerase()の.firstを単一のイテレータバージョンに渡すことによって最初の要素erase()

擬似コード:

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

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

2
問題は、すべての重複ではなく、1つの重複を削除することについて質問していると思います。
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から削除される単一の要素を指すイテレータ。」
アンドリュー

-3

実際、正解は次のとおりです。

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

1
場合値はマルチセットに存在しない、それが原因未定義の動作を
kien_coi_1997 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.