Как удалить элемент из map c
Здравствуйте, уважаемые знатоки C++.
Нужно удалять элементы из std::map согласно некотому условию. Всегде ли будет работать такой трюк:
std::map m; std::map::iterator cur, end; cur = m.begin(); end = m.end(); while (cur != end) < if (is_not_OK(*cur)) m.erase(cur++); else ++cur; >
Re: удаление элементов из std::map
| От: | Bell | |
| Дата: | 02.05.07 13:53 | |
| Оценка: | 6 (1) -1 | |
Здравствуйте, sigsegv, Вы писали:
S>Здравствуйте, уважаемые знатоки C++.
S>Нужно удалять элементы из std::map согласно некотому условию. Всегде ли будет работать такой трюк:
Да, это стандартный прием.
Любите книгу — источник знаний (с) М.Горький
Re[2]: удаление элементов из std::map
| От: | Sk0rp | |
| Дата: | 02.05.07 15:30 | |
| Оценка: | 1 (1) -2 | |
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, sigsegv, Вы писали:
S>>Здравствуйте, уважаемые знатоки C++.
S>>std::map m; S>>std::map::iterator cur, end; S>>cur = m.begin(); S>>end = m.end(); S>>while (cur != end) S>>< S>> if (is_not_OK(*cur)) S>> m.erase(cur++); > else S>> ++cur; S>>>
S>>Нужно удалять элементы из std::map согласно некотому условию. Всегде ли будет работать такой трюк:
B>.
B>Да, это стандартный прием.
не согласен, при удалении может в общем случае произойти реаллокация и итератор станет абсолютно невалидным.
стандартный прием это воспользоваться тем, что erase возвращает итератор на следующий после последнего удаленого элемент:
while(cur != m.end()) < if(is_not_OK(*cur)) cur = m.erase(cur); else ++cur; >
заранее запомненный m.end() также скорее всего окажется невалидным.
Re[3]: удаление элементов из std::map
| От: | Bell | |
| Дата: | 02.05.07 15:42 | |
| Оценка: | 1 (1) | |
Здравствуйте, Sk0rp, Вы писали:
S>не согласен, при удалении может в общем случае произойти реаллокация и итератор станет абсолютно невалидным.
Ассоциативные контейнеры не попадают в этот «общий случай»:
23.1.2/8
The insert members shall not affect the validity of iterators and references to the container,
and the erase members shall invalidate only iterators and references to the erased elements.
Еще раз обращаю внимание на конструкцию
m.erase(cur++);
Т.е. после вызова erase у нас остается валидный итератор.
Подробнее можно посмотреть в поиске.
S>стандартный прием это воспользоваться тем, что erase возвращает итератор на следующий после последнего удаленого элемент:
S>
S>while(cur != m.end()) S> < S>if(is_not_OK(*cur)) S> cur = m.erase(cur); S> else S> ++cur; S>> S>
Операция erase для ассоциативных контейнеров по стандарту возвращает void — смотри таблицу 69 в 23.1.2/7. То, что реализация STL от Dinkumware (поставляется с MSVC) возвращает итератор, вовсе не означает, что другие реализации делают так же.
S>заранее запомненный m.end() также скорее всего окажется невалидным.
смотри выше.
Итого имеем 3 неверных утверждения из трех
Любите книгу — источник знаний (с) М.Горький
Re[4]: удаление элементов из std::map
| От: | Константин Л. |
| Дата: | 02.05.07 15:54 |
| Оценка: |
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, Sk0rp, Вы писали:
S>>не согласен, при удалении может в общем случае произойти реаллокация и итератор станет абсолютно невалидным.
B>Ассоциативные контейнеры не попадают в этот "общий случай":
B>
B>23.1.2/8
B>The insert members shall not affect the validity of iterators and references to the container,
B>and the erase members shall invalidate only iterators and references to the erased elements.
B>Еще раз обращаю внимание на конструкцию
B>
B>m.erase(cur++);
B>Т.е. после вызова erase у нас остается валидный итератор.
B>Подробнее можно посмотреть в поиске.
Эти 2 предложения противоречивы. Разве нет?
Re[4]: удаление элементов из std::map
| От: | Sk0rp | |
| Дата: | 02.05.07 16:37 | |
| Оценка: | -1 | |
Здравствуйте, Bell, Вы писали:
B>Операция erase для ассоциативных контейнеров по стандарту возвращает void — смотри таблицу 69 в 23.1.2/7. То, что реализация STL от Dinkumware (поставляется с MSVC) возвращает итератор, вовсе не означает, что другие реализации делают так же.
map::erase
Removes an element or a range of elements in a map from specified positions or removes elements that match a specified key.
iterator erase( iterator _Where ); iterator erase( iterator _First, iterator _Last ); size_type erase( const key_type& _Key );
Parameters
_Where
Position of the element to be removed from the map.
_First
Position of the first element removed from the map.
_Last
Position just beyond the last element removed from the map.
_Key
The key value of the elements to be removed from the map.
Return Value
For the first two member functions, a bidirectional iterator that designates the first element remaining beyond any elements removed, or a pointer to the end of the map if no such element exists.
For the third member function, returns the number of elements that have been removed from the map.
Send feedback on this topic to Microsoft
© 1992-2002 by P. J. Plauger. All rights reserved.
© Microsoft Corporation. All rights reserved.
Re[5]: удаление элементов из std::map
| От: | . | |
| Дата: | 02.05.07 16:50 | |
| Оценка: | 1 (1) | |
Здравствуйте, Константин Л., Вы писали:
КЛ>Эти 2 предложения противоречивы. Разве нет?
Нет. Я тоже как-то ошибся на этом.
m.erase(cur++) означает: создать временную копию cur, увеличить значение cur (он становится указывающим на следующий элемент), передать временную копию в erase, удаляется текущцй элемент, грохнуть временную копию. В итоге cur становтся указывающим на следующий элемент, невалидный итератор "забыт", элемент удалён.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: удаление элементов из std::map
| От: | ShaggyOwl | http://www.rsdn.org |
| Дата: | 02.05.07 17:13 | |
| Оценка: |
Здравствуйте, Sk0rp, Вы писали:
B>>Операция erase для ассоциативных контейнеров по стандарту возвращает void — смотри таблицу 69 в 23.1.2/7. То, что реализация STL от Dinkumware (поставляется с MSVC) возвращает итератор, вовсе не означает, что другие реализации делают так же.
S>Send feedback on this topic to Microsoft
S>© 1992-2002 by P. J. Plauger. All rights reserved.
S>© Microsoft Corporation. All rights reserved.
Если собирать следующий пример с STLPort
std::mapint, int> m; std::mapint, int>::iterator it = m.begin(); it = m.erase( it );
На третьей строки имеем
Хорошо там, где мы есть! 🙂
Re: удаление элементов из std::map
| От: | latemic |
| Дата: | 02.05.07 19:12 |
| Оценка: |
Здравствуйте, sigsegv, Вы писали:
S>Здравствуйте, уважаемые знатоки C++.
S>Нужно удалять элементы из std::map согласно некотому условию. Всегде ли будет работать такой трюк:
Да такой трюк будет работать всегда. Достаточно посмотреть реализацию операции постфиксного инкремента для итератора:
iterator& operator++() < // preincrement ++(*(const_iterator *)this); return (*this); > iterator operator++(int) < // postincrement iterator _Tmp = *this; ++*this; return (_Tmp); >
Этот код демонстрирует, что операция постфиксного инкремента возвращает копию объекта, которая станет аргуменитом метода map::erase(), в то время как оригинальный объект будет уже другим.
"Если нельзя, но очень хочется. то можно"
Re[5]: удаление элементов из std::map
| От: | Bell |
| Дата: | 02.05.07 20:19 |
| Оценка: |
Здравствуйте, Sk0rp, Вы писали:
S>map::erase
S>Removes an element or a range of elements in a map from specified positions or removes elements that match a specified key.
S>© 1992-2002 by P. J. Plauger. All rights reserved.
S>© Microsoft Corporation. All rights reserved.
Я знаю что написано в MSDN по этому поводу. Именно это я и имел ввиду:
B>>Операция erase для ассоциативных контейнеров по стандарту возвращает void — смотри таблицу 69 в 23.1.2/7. То, что реализация STL от Dinkumware (поставляется с MSVC) возвращает итератор, вовсе не означает, что другие реализации делают так же.
Однако не нужно забывать, что существует еще стандарт языка и его стандартной библиотеки, и многие реализации этому стандарту следуют.
Любите книгу — источник знаний (с) М.Горький
Re[5]: удаление элементов из std::map
| От: | Константин Л. |
| Дата: | 03.05.07 08:49 |
| Оценка: |
Здравствуйте, Константин Л., Вы писали:
КЛ>Здравствуйте, Bell, Вы писали:
B>>Здравствуйте, Sk0rp, Вы писали:
S>>>не согласен, при удалении может в общем случае произойти реаллокация и итератор станет абсолютно невалидным.
B>>Ассоциативные контейнеры не попадают в этот "общий случай":
B>>
B>>23.1.2/8
B>>The insert members shall not affect the validity of iterators and references to the container,
B>>and the erase members shall invalidate only iterators and references to the erased elements.
B>>Еще раз обращаю внимание на конструкцию
B>>
B>>m.erase(cur++); >
КЛ>B>Т.е. после вызова erase у нас остается валидный итератор.
B>>Подробнее можно посмотреть в поиске.
КЛ>Эти 2 предложения противоречивы. Разве нет?
ааа, тут же постинкремент
КЛ>[]
Re[5]: удаление элементов из std::map
| От: | Андрей Коростелев | http://www.korostelev.net/ |
| Дата: | 03.05.07 09:56 | |
| Оценка: |
Здравствуйте, Sk0rp, Вы писали:
B>>То, что реализация STL от Dinkumware (поставляется с MSVC) возвращает итератор, вовсе не означает, что другие реализации делают так же.
S>map::erase
S>Removes an element or a range of elements in a map from specified positions or removes elements that match a specified key.
Поясню, почему тебе лепят минусы. Как упомянуто в правилах форума
Автор: Павел Кузнецов
Дата: 25.03.03
, тут отсуждаются технические аспекты использования языков C, C++ и C++/CLI в том виде, как они определены соответствующими стандартами.
Ты же ссылаешься на документацию (MSDN), поставляемую разработчиком конкретного компялятора (MSVC), или же предлагаешь system-specific решения (ветка "Работа с каталогами в си"). Если стандарт тяжело воспринимать, посмотри Страуструпа, это фактически тот же стандарт, написанный более человеческим языком.
Как удалить элемент из map java
Для удаления элемента из Map необходимо вызвать метод remove(key) и передать ключ элемента, который нужно удалить.
MapString, Integer> map = new HashMap<>(); map.put("one", 1); map.put("two", 2); map.put("three", 3); // Удаляем элемент с ключом "two" map.remove("two"); System.out.println(map); // =>
Если элемент с заданным ключом не существует, то метод remove ничего не изменит в Map
6.12.5. Удаление элементов map
Существуют три формы функции-члена erase() для удаления элементов отображения. Для единственного элемента используется erase() с ключом или итератором в качестве аргумента, а для последовательности эта функция вызывается с двумя итераторами. Например, мы могли бы позволить удалять элементы из text_map таким образом:
cout "введите удаляемое слово: ";
if ( text_map-erase( remova1_word ))
cout "ok: " remova1_word " удалено ";
else cout "увы: " remova1_word " не найдено! ";
Альтернативой является проверка: действительно ли слово содержится в text_map?
where = text_map.find( remova1_word );
if ( where == text_map-end() )
cout "увы: " remova1_word " не найдено! ";
cout "ok: " remova1_word " удалено! ";
В нашей реализации text_map с каждым словом сопоставляется множество позиций, что несколько усложняет их хранение и извлечение. Вместо этого можно было бы иметь по одной позиции на слово. Но контейнер map не допускает дублирующиеся ключи. Нам следовало бы воспользоваться классом multimap, который рассматривается в разделе 6.15.
Определите отображение, где ключом является фамилия, а значением – вектор с именами детей. Поместите туда как минимум шесть элементов. Реализуйте возможность делать запрос по фамилии, добавлять имена и распечатывать содержимое.
Измените программу из предыдущего упражнения так, чтобы вместе с именем ребенка записывалась дата его рождения: пусть вектор-значение хранит пары строк – имя и дата.
Приведите хотя бы три примера, в которых нужно использовать отображение. Напишите определение объекта map для каждого примера и укажите наиболее вероятный способ вставки и извлечения элементов.
Читайте также
14.4.6. Удаление вершины дерева и удаление дерева: tdelete() и tdestroy()
14.4.6. Удаление вершины дерева и удаление дерева: tdelete() и tdestroy() Наконец, вы можете удалить элементы из дерева и, на системах GLIBC, удалить само дерево целиком:void *tdelete(const void *key, void **rootp,int (*compare)(const void*, const void*));/* Расширение GLIBC, в POSIX нет: */void tdestroy(void *root, void (*free_node)(void *nodep));Аргументы
Добавление и удаление элементов Web-страницы
Добавление и удаление элементов Web-страницы А теперь — высший пилотаж Web-программирования! Программное добавление на Web-страницу новых элементов и программное же их удаление. Для этого применяют методы объекта DomHelper.Метод append добавляет новый элемент Web-страницы в
Добавление и удаление элементов Web-страницы
Добавление и удаление элементов Web-страницы А теперь — высший пилотаж Web-программирования! Программное добавление на Web-страницу новых элементов и программное же их удаление. Для этого применяют методы объекта DomHelper.Метод append добавляет новый элемент Web-страницы в
Добавление новых элементов в панель элементов управления
Добавление новых элементов в панель элементов управления Чтобы получить возможность использовать элемент управления ActiveX, выполните следующее.1. Установите программное обеспечение элемента управления на жесткий диск.Мне кажется, это имеет смысл.2. Зарегистрируйте
Добавление и удаление элементов таблицы
Добавление и удаление элементов таблицы При редактировании таблицы иногда бывает необходимо добавлять в нее дополнительные элементы – строки или столбцы. Для этого выделите такое количество строк или столбцов, какое нужно добавить. Затем перейдите на вкладку Работа с
8.1.14. Удаление из массива элементов равных nil
8.1.14. Удаление из массива элементов равных nil Метод compact (и его вариант compact! для модификации на месте) удаляет из массива элементы равные nil, оставляя все остальные без изменения:a = [1, 2, nil, 3, nil, 4, 5]b = a.compact # [1, 2, 3, 4, 5]a.compact! # а равно [1, 2, 3, 4,
8.1.15. Удаление заданных элементов из массива
8.1.15. Удаление заданных элементов из массива В Ruby легко удалить элементы из массива - для этого даже существует много способов. Чтобы удалить элемент с известным индексом, достаточно вызвать метод delete_at:a = [10, 12, 14, 16, 18]a.delete_at(3) # Возвращает 16.# а равно [10, 12, 14, 18]a.delete_at(9) #
Динамическое добавление (и удаление) элементов управления
Динамическое добавление (и удаление) элементов управления Но что делать, если нужно изменить содержимое Panel в среде выполнения? Соответствующий процесс должен показаться вам очень знакомым, если вы внимательно прочитали материал книги, посвященный работе с Windows Forms.
Хранение элементов в коллекциях и получение элементов из коллекций
Хранение элементов в коллекциях и получение элементов из коллекций Коллекции — это такие объекты, в экземплярах которых могут храниться другие объекты. Одна из самых распространенных разновидностей коллекций — это массив, который инстанцирует NSArray или NSMutableArray. В
Вставка и удаление элементов в односвязном списке
Вставка и удаление элементов в односвязном списке А каким образом можно вставить новый элемент в связный список? Или удалить? Оказывается, что для выполнения этих операций требуется выполнить небольшую работу с указателями.Для односвязного списка существует только
Вставка и удаление элементов в двухсвязном списке
Вставка и удаление элементов в двухсвязном списке Каким образом вставлять новый узел в двухсвязный список? В односвязном списке для этого нужно было разорвать одну ссылку и вставить две новых, а для двухсвязного списка потребуется разорвать две ссылки и вставить четыре
Удаление элементов из хеш-таблицы с линейным зондированием
Удаление элементов из хеш-таблицы с линейным зондированием Прежде чем приступить к рассмотрению конкретного кода, рассмотрим удаление элементов из хеш-таблицы. Эта задача кажется достаточно простой: необходимо выполнить хеширование ключа элемента, который нужно
6.12.5. Удаление элементов map
6.12.5. Удаление элементов map Существуют три формы функции-члена erase() для удаления элементов отображения. Для единственного элемента используется erase() с ключом или итератором в качестве аргумента, а для последовательности эта функция вызывается с двумя итераторами.
Узлы элементов
Узлы элементов Каждому элементу XML-документа соответствует узел элемента. Дочерними узлами узла элемента могут быть узлы его дочерних элементов, а также узлы комментариев, инструкций по обработке и текстовые узлы, которые представляют его непосредственное содержимое.
Удаление элементов Проводника
Удаление элементов Проводника Существует возможность запрета отображения некоторых элементов Проводника. В данном разделе книги мы подробнее познакомимся с этой возможностью.Удаление меню ФайлС помощью несложной операции можно удалить меню Файл из главного меню как
Вставка и удаление элементов из std::map в цикле
Можно ли в цикле по std::map на каждом шаге совершать несколько удалений и вставок элементов в этот же контейнер? Т.е. будет ли правильно работать следующий код?
std::map my_map; for (auto&& it = my_map.begin(); it != my_map.end();) < if (pair.second == 42) it = my_map[pair.first].erase(it); if (2 + 2 == 4) it = my_map.emplace(42, 42).first; //. if (no_insert_and_no_erase) ++it; >
Отслеживать
8,592 4 4 золотых знака 29 29 серебряных знаков 53 53 бронзовых знака
задан 15 мая 2017 в 19:48
31 1 1 серебряный знак 2 2 бронзовых знака
Ну по идее должен, почему бы ему не работать? Если только скомпилируется.
15 мая 2017 в 19:50
@VladD я исхожу из той логики, что при удалении возвращенный итератор может проскочить вставленный на этой итерации элемент
15 мая 2017 в 19:53
Ну у вас же сначала удаление?
15 мая 2017 в 19:54
@VladD нет, имеется в виду, что порядок произвольный и количество тоже
15 мая 2017 в 19:55
Только вот непонятна логика со вставкой: если вставка будет в конец, вы перепрыгнете весь список?
15 мая 2017 в 19:55
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
pair < iterator, bool>container::emplace (args) //std::map
iterator container::emplace (args) // std::multimap
Для всех контейнеров(ассоциативных и неупорядоченных) операция вставки сохраняет корректность ссылок на существующие элементы. Для ассоциативных контейнеров все итераторы установленные на существующие элементы остаются корректными.
iterator container::erase(iterator) (С++11)
При удалении элемента главное не удалить итератор ссылающийся на этот элемент.
std::map coll; . for(auto pos = coll.begin(); pos != coll.end(); ++pos) < if(pos->second == value) coll.erase(pos); // Ошибка во время выполнения >
В С++11 функция-член erase всегда возвращает значение следующего элемента.
std::map coll; . for(auto pos = coll.begin(); pos != coll.end();) < if(pos->second == value) < pos = coll.erase(pos); // C++11 >else < ++pos; >>
Если вы хотите заменить какой-то ключ элемента коллекции, то для этого существует только одна возможность: необходимо заменить старый элемент новым с тем же значением.
template bool replaceKey(Cont& c, const typename Cont::key_type& oldKey, const typename Cont::key_type& newKey) < typename Cont::iterator pos; pos = c.find(oldKey); if(pos != c.end()) < //Вставка нового элемента c.insert( typename Cont::value_type(newKey, pos->second) ); //Удаляем старый элемент c.erase(pos); return true; > else < return false; >>
Для мапы также существует более простой способ:
coll["newKey"] = coll["oldKey"]; coll.erase("oldKey");