У 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);
}

Я гадаю, існує більш чистий спосіб зробити те саме. Але це робить роботу.


10
Це нічим не відрізняється від того, про що йдеться.
Трубадур,

2
Я згоден! Не має сенсу. Ще 12 людей побачили у відповіді щось корисне, тож я знаю, що я не збожеволію.
user2251346

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
Порівняно з рішенням, яке я запропонував у питанні, ваш код виконує два пошуки (знайдіть + рівний_діапазон) замість одного, який є неефективним
Мартін,

оскільки це однакова складність, мені дуже подобається ця відповідь. Дякую
Кристал

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));

1
Якщо значення не існує в мультимножині, це спричиняє невизначену поведінку .
kien_coi_1997
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.