C++遍历中删除std--map元素
- 格式:pdf
- 大小:126.82 KB
- 文档页数:2
map集合特点及遍历、清除数据的⽅法⼀、map集合特点:⽆序、以键值对的形式添加元素,键不能重复,值可以重复没有继承Collection接⼝。
如下有⼀map集合:Map<String, String> map=new HashMap<String, String>();map.put("张⼀", "男");map.put("张⼆", "男");map.put("张三", "男");map.put("张四", "男");⼆、map集合遍历//第⼀种通过加强for循环map.keySet(),然后通过键key获取到value值for(String s:map.keySet()){ System.out.println("key : "+s+" value : "+map.get(s));}注:遍历值的⽅法为map.values();//第⼆种通过Map.Entry<String, String>的加强for循环遍历输出键key和值valuefor(Map.Entry<String, String> entry : map.entrySet()){ System.out.println("键 key :"+entry.getKey()+" 值value :"+entry.getValue());}//第三种Iterator遍历获取,然后获取到Map.Entry<String, String>,再得到getKey()和getValue()Iterator<Map.Entry<String, String>> it=map.entrySet().iterator();while(it.hasNext()){ Map.Entry<String, String> entry=it.next(); System.out.println("键key :"+entry.getKey()+" value :"+entry.getValue());}三、清除集合的数据//移除指定的元素Map<String,Integer> m = new HashMap<String,Integer>();m.put("zhangsan", 19);m.put("lisi", 49); m.remove("zhangsan");//通过键的映射关系,则将其从此映射中移除//清空集合的全部数据m.clear();。
C#在foreach遍历删除集合中元素的三种实现⽅法前⾔在foreach中删除元素时,每⼀次删除都会导致集合的⼤⼩和元素索引值发⽣变化,从⽽导致在foreach中删除元素时会抛出异常。
集合已修改;可能⽆法执⾏枚举操作。
⽅法⼀:采⽤for循环,并且从尾到头遍历如果从头到尾正序遍历删除的话,有些符合删除条件的元素会成为漏⽹之鱼;正序删除举例:List<string> tempList = new List<string>() { "a","b","b","c" };for (int i = 0; i < tempList.Count; i++){if (tempList[i] == "b"){tempList.Remove(tempList[i]);}}tempList.ForEach(p => {Console.Write(p+",");});控制台输出结果:a,b,b,c有两个2没有删除掉;这是因为当i=1时,满⾜条件执⾏删除操作,会移除第⼀个b,接着第⼆个b会前移到第⼀个b的位置,即游标1对应的是第⼆个b。
接着遍历i=2,也就跳过第⼆个b。
⽤for倒序遍历删除,从尾到头List<string> tempList = new List<string>() { "a","b","b","c" };for (int i = tempList.Count-1; i>=0; i--){if (tempList[i] == "b"){tempList.Remove(tempList[i]);}}tempList.ForEach(p => {Console.Write(p+",");});控制台输出结果:a,c,这次删除了所有的b;⽅法⼆:使⽤递归使⽤递归,每次删除以后都从新foreach,就不存在这个问题了;static void Main(string[] args){List<string> tempList = new List<string>() { "a","b","b","c" };RemoveTest(tempList);tempList.ForEach(p => {Console.Write(p+",");});}static void RemoveTest(List<string> list){foreach (var item in list){if (item == "b"){list.Remove(item);RemoveTest(list);return;}}}控制台输出结果:a,c,正确,但是每次都要封装函数,通⽤性不强;⽅法三:通过泛型类实现IEnumeratorstatic void Main(string[] args){RemoveClass<Group> tempList = new RemoveClass<Group>();tempList.Add(new Group() { id = 1,name="Group1" }) ;tempList.Add(new Group() { id = 2, name = "Group2" });tempList.Add(new Group() { id = 2, name = "Group2" });tempList.Add(new Group() { id = 3, name = "Group3" });foreach (Group item in tempList){if (item.id==2){tempList.Remove(item);}}foreach (Group item in tempList){Console.Write(item.id+",");}//控制台输出结果:1,3public class RemoveClass<T>{RemoveClassCollection<T> collection = new RemoveClassCollection<T>(); public IEnumerator GetEnumerator(){return collection;}public void Remove(T t){collection.Remove(t);}public void Add(T t){collection.Add(t);}}public class RemoveClassCollection<T> : IEnumerator{List<T> list = new List<T>();public object current = null;Random rd = new Random();public object Current{get { return current; }}int icout = 0;public bool MoveNext(){if (icout >= list.Count){return false;}else{current = list[icout];icout++;return true;}}public void Reset(){icout = 0;}public void Add(T t){list.Add(t);}public void Remove(T t){if (list.Contains(t)){if (list.IndexOf(t) <= icout){icout--;}list.Remove(t);}}}总结以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,谢谢⼤家对的⽀持。
在C++中,可以使用迭代器(iterator)或基于范围的for循环来遍历map。
1. 使用迭代器遍历map:```cpp#include <iostream>#include <map>using namespace std;int main() {map<string, int> myMap;myMap["one"] = 1;myMap["two"] = 2;myMap["three"] = 3;// 使用迭代器遍历mapfor (map<string, int>::iterator it = myMap.begin(); it != myMap.end(); it++) {cout << "Key: " << it->first << ", Value: " << it->second << endl;}return 0;}```2. 使用基于范围的for循环遍历map:```cpp#include <iostream>#include <map>using namespace std;int main() {map<string, int> myMap;myMap["one"] = 1;myMap["two"] = 2;myMap["three"] = 3;// 使用基于范围的for循环遍历mapfor (const auto &pair : myMap) {cout << "Key: " << pair.first << ", Value: " << pair.second<< endl;}return 0;}```在这两种方法中,迭代器遍历map可以更灵活地访问元素,而基于范围的for循环则更简洁。
C++如何删除map容器中指定值的元素详解前⾔⼤家都知道map容器是C++ STL中的重要⼀员,平时会遇到删除map容器中value为指定元素的问题,例如删除所有字符串为"123"或者能整除3的元素。
⼀、map容器下的⽅法说明由于map容器下的⽅法较多,这⾥只列举代码中⽤到的⼏个⽅法:insert()⽅法://插⼊val到pos的后⾯,然后返回⼀个指向这个元素的迭代器iterator insert( iterator pos, const pair<KEY_TYPE,VALUE_TYPE> &val );//插⼊start到end的元素到map中void insert( input_iterator start, input_iterator end );//只有在val不存在时插⼊val。
返回值是⼀个指向被插⼊元素的迭代器和⼀个描述是否插⼊的bool值pair<iterator, bool> insert( const pair<KEY_TYPE,VALUE_TYPE> &val );erase()⽅法://erase()函数删除在pos位置的元素,或者删除在start和end之间的元素,或者删除那些值为key的所有元素void erase( iterator pos );void erase( iterator start, iterator end );size_type erase( const KEY_TYPE &key );iterator迭代器。
⼆、删除map容器中指定的字符串下⾯代码中map容器的value对应的是⼀个string类型的指针,在初始化时类似于string *p = new string("123");。
/*** @FileName map_del_str.cpp* @Describe A simple example for deleting an element of string in map.* @Author vfhky 2016-06-26 10:26 https:///cseries/mapdelintstring.html* @Compile g++ map_del_str.cpp -o map_del_str* @Reference*/#include <iostream>#include <map>using namespace std;#define TOTAL 10#define DEL_STR "123"/*** 删除map中所有元素为str的数据*/void fun( map<int, string *> &map1, const string str ){map<int, string *>::iterator it;int i_Total = 0;for( it=map1.begin(); it!=map1.end(); ){if( *(it->second) == str ){/*** 123 123 123 123 123 123 123 123 123 123*/cout << *(it->second) << " ";//⼀定要先释放内存的控制delete it->second;it->second = NULL;//再删除迭代map1.erase(it++);++i_Total;}elseit++;}}//i_Total=[10]cout << endl << "i_Total=[" << i_Total << "]" << endl;}int main( int argc, char **argv ){map<int, string *> map1;//初始化map1for( int i=0; i<TOTAL; i++ ){map1.insert( pair<int, string *>(i,new string("123")) );//map1[i] = new string("123");}//删除为DEL_STR的元素fun( map1, DEL_STR );//查看最后的数据map<int, string *>::iterator it1;for( it1=map1.begin(); it1!=map1.end(); ++it1 ){cout << "map1[" << it1->first << "]=[" << *(it1->second) << "]" << endl;}return 0;}效果如下图所⽰:三、删除map容器中指定的整型数据下⾯代码中map容器的value对应的是⼀个int数据,在初始化时可以直接使⽤map1[i] = i语句。
Java如何在List或Map遍历过程中删除元素遍历删除List或Map中的元素有很多种⽅法,当运⽤不当的时候就会产⽣问题。
下⾯通过这篇⽂章来再学习学习吧。
⼀、List遍历过程中删除元素使⽤索引下标遍历的⽅式⽰例:删除列表中的2public static void main(String[] args) {List<Integer> list = new ArrayList<Integer>();list.add(1);list.add(2);list.add(2);list.add(3);list.add(4);for (int i = 0; i < list.size(); i++) {if(2 == list.get(i)){list.remove(i);}System.out.println(list.get(i));}System.out.println("list=" + list.toString());}输出结果:1234list=[1, 2, 3, 4]问题:结果显⽰只删除了⼀个2,另⼀个2被遗漏了,原因是:删除了第⼀个2后,集合⾥的元素个数减1,后⾯的元素往前移了1位,导致了第⼆个2被遗漏了。
使⽤For循环遍历的⽅式⽰例:public static void listIterator2(){List<Integer> list = new ArrayList<Integer>();list.add(1);list.add(2);list.add(2);list.add(3);list.add(4);for (int value : list) {if(2 == value){list.remove(value);}System.out.println(value);}System.out.println("list=" + list.toString());}结果:Exception in thread "main" 12java.util.ConcurrentModificationExceptionat java.util.ArrayList$Itr.checkForComodification(Unknown Source)at java.util.ArrayList$Itr.next(Unknown Source)at test.ListIterator.listIterator2(ListIterator.java:39)at test.ListIterator.main(ListIterator.java:10)说明:jdk中对ConcurrentModificationException的描述:public class ConcurrentModificationException extendsRuntimeException当⽅法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
关于STL的erase()陷阱-迭代器失效问题的总结下⾯材料整理⾃Internet&著作。
STL中的容器按存储⽅式分为两类,⼀类是按以数组形式存储的容器(如:vector 、deque);另⼀类是以不连续的节点形式存储的容器(如:list、set、map)。
在使⽤erase⽅法来删除元素时,需要注意⼀些问题。
1.list,set,map容器在使⽤ list、set 或 map遍历删除某些元素时可以这样使⽤:1.1 正确写法1std::list< int> List;std::list< int>::iterator itList;for( itList = List.begin(); itList != List.end(); ){if( WillDelete( *itList) ){itList = List.erase( itList);}elseitList++;}1.2 正确写法2std::list< int> List;std::list< int>::iterator itList;for( itList = List.begin(); itList != List.end(); ){if( WillDelete( *itList) ){List.erase( itList++);}elseitList++;}1.3 错误写法1std::list< int> List;std::list< int>::iterator itList;for( itList = List.begin(); itList != List.end(); itList++){if( WillDelete( *itList) ){List.erase( itList);}}1.4 错误写法2std::list< int> List;std::list< int>::iterator itList;for( itList = List.begin(); itList != List.end(); ){if( WillDelete( *itList) ){itList = List.erase( ++itList);}elseitList++;}1.5 分析正确使⽤⽅法1:通过erase⽅法的返回值来获取下⼀个元素的位置正确使⽤⽅法2:在调⽤erase⽅法之前先使⽤ “++”来获取下⼀个元素的位置错误使⽤⽅法1:在调⽤erase⽅法之后使⽤“++”来获取下⼀个元素的位置,由于在调⽤erase⽅法以后,该元素的位置已经被删除,如果在根据这个旧的位置来获取下⼀个位置,则会出现异常。
C++容器:在遍历过程中删除元素C++11之后,标准库引⼊了⼤量由基本数据结构封装⽽成的容器类型。
容器的引⼊,⼀定程度上降低Cpp的上⼿难度。
在实际的开发过程中,经常需要根据业务需求,在遍历过程中从容器⾥删除指定的元素。
⽽⼀些不规范的使⽤⽅式,将埋下稳定性风险。
⼀、推荐模板对于在遍历过程中删除指定元素,推荐使⽤以下模板:for(auto it = _container.begin(); it != _container.end(); ) {if(__pred(*it)) {//do something with (*it);it = _container.erase(it);} else {++it;}}⼆、常见遍历模式的缺陷1. 下⾯这种遍历⽅式应该是⼤家最容易想到的:for(auto it = _container.begin(); it != _container.end(); ++it) {if(__pred(*it)) {_container.erase(it);}}这种遍历⽅式的问题⽐较明显,主要是两种:间隔遍历,部分元素被跳过;heap-buffer-used-after-free,也就是使⽤被释放的动态内存;第⼀类问题主要出现在以vector为代表的容器中int main() {std::vector<int> nums{1,2,3,4,5,6,7,8};for(auto iter = nums.begin(); iter != nums.end(); ++iter) {if(*iter == 4) {nums.erase(iter);} else {std::cout<< *iter <<"";}}std::cout<<std::endl;return0;} g++ _Container.cpp -o _Container && _Container可以看到删除元素4之后,其之后的5也被循环跳过了。
C++(⼗⼀)—map的插⼊、查找、删除 标准库map类型是⼀种以键-值(key-value)存储的数据类型。
map是STL的⼀个关联容器。
它提供⼀对⼀(其中第⼀个可以称为关键字,每个关键字只能在map中出现⼀次,第⼆个可能称为该关键字的值)的数据处理能⼒,由于这个特性,它完成有可能在我们处理⼀对⼀数据的时候,在编程上提供快速通道。
这⾥说下map内部数据的组织,map内部⾃建⼀颗红⿊树(⼀种⾮严格意义上的平衡⼆叉树),这颗树具有对数据⾃动排序的功能,所以在map内部所有的数据都是有序的。
1、map特点 map是⼀类关联式容器。
它的特点是增加和删除节点对迭代器的影响很⼩,除了那个操作节点,对其他的节点都没有什么影响。
对于迭代器来说,可以修改实值,⽽不能修改key。
⾃动建⽴Key - value的对应。
key 和 value可以是任意你需要的类型。
根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
快速插⼊Key -Value 记录。
快速删除记录,根据Key 修改value记录。
遍历所有记录。
2、map对象的⼀些基本操作 因此,若只是查找该元素是否存在,可以使⽤函数count(k),该函数返回的是k出现的次数;若是想取得key对应的值,可以使⽤函数find(k),该函数返回的是指向该元素的迭代器。
第⼀种:⽤count函数来判定关键字是否出现,其缺点是⽆法定位数据出现位置,由于map的特性,⼀对⼀的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了 第⼆种:⽤find函数来定位数据出现位置,它返回的⼀个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器。
查找map中是否包含某个关键字条⽬⽤find()⽅法,传⼊的参数是要查找的key,在这⾥需要提到的是begin()和end()两个成员,分别代表map对象中第⼀个条⽬和最后⼀个条⽬,这两个数据的类型是iterator.map<char, int> p;//map中插⼊元素// method_1p.insert(make_pair('a', 10));p.insert(make_pair('b', 9));// method_2p.insert(pair<char, int>('c', 8));p.insert(pair<char, int>('d', 7));//method_3p.insert(map<char, int>::value_type('e', 6));#include<iostream>#include<algorithm>#include<stdio.h>#include <vector>#include<string>#include<map>using namespace std;int main(){map<char, int> p;//map中插⼊元素p.insert(make_pair('a',10));p.insert(make_pair('c',9 ));p.insert(make_pair('b',10 ));//采⽤下标的⽅法读取map中元素时,若map中不存在该元素,则会在map中插⼊。
c语言map的用法希望对你有帮助哦!c语言map的用法C++实际开发的过程会经常使用到map。
map是一个key-value值对,key唯一,可以用find进行快速的查找。
其时间复杂度为O(logN),如果采用for循环进行遍历数据时间复杂度为O(N)。
如果map中的数据量比较少时,采用find和for循环遍历的效率基本没有太大的区别,但是在实际的开发过程中,存储在map中的数据往往是大量的,这个时候map采用find方式效率比遍历效率高的多。
确定采用find方式查找数据后,我们需要考虑存储map的空间复杂度,对于基础数据类型的数据(int char等)这里就不做讨论。
本文讨论的是map中存储的数据结构struct情况。
1、如果map中的key为struct此时,需要先对struct进行操作符重载,关于这部分内容可以参考C++ 重载操作符示例2、map中的key 只能是对象,而不能是指针。
(这一点尤为重要)。
下面给出三个map定义进行说明:std::map* pmapNHSymbolInfo1std::map* pmapNHSymbolInfo2std::map* pmapNHSymbolInfo2其中,pmapNHSymbolInfo1、pmapNHSymbolInfo2中使用find正常,遍历也正常,pmapNHSymbolInfo3使用find查找不到对应的数据(数据已经存在,find不到,遍历可以找到)原因:std::map* pmapNHSymbolInfo2在find的时候是根据指针进行查找的。
而在数据insert时,数据都是new的,每次new出的地址是不一样的,在find数据时,根据地址查找结果就找不到数据。
通过遍历是取出地址中内容一一比较,这样能够找到数据。
pmapNHSymbolInfo1、pmapNHSymbolInfo2两种方式都可以使用find方式查找数据,但是pmapNHSymbolInfo1中Stru_NHSymbol为对象,这样会使map占用空间比较大,pmapNHSymbolInfo2的Stru_NHSymbol为指针,存储时地址占用空间小,但是每次都是new 处理来的,所有一定要记住使用完成后一定要delete,否则会出现内存泄露。