从嵌套在 std::map 中的 std::list 中删除元素的最佳方法
Posted
技术标签:
【中文标题】从嵌套在 std::map 中的 std::list 中删除元素的最佳方法【英文标题】:Best way to remove an element from a std::list nested inside a std::map 【发布时间】:2020-07-08 09:16:13 【问题描述】:正如标题所说,我想知道从满足特定条件(名称和日期)的地图内的列表中删除元素的最有效方法是什么。这是我提供的功能:
void Register::DeleteActivity(const Date &f,const std::string &a)
auto it = Registro.find(f);
if(it != Registro.end())
if(it->second.empty())
std::cout <<"Error"<<std::endl;
else
for(auto ip = it->second.begin(); ip != it->second.end();)
if(ip->getName() == a && ip->getStartdate() == f)
ip->printInfo();
it->second.erase(ip);
else
ip++;
else
std::cout<< "DeleteActivity::day not found"<<std::endl;
这是完整的课程:
class Register
private:
map<Date,std::list<Activity>> Registro;
public:
Register();
void addActivity(Date &z, Activity &n);
void editActivity(const Date &a, const std::string &c, Date k, const std::string newname);
void DeleteActivity(const Date &f, const std::string &a);
【问题讨论】:
【参考方案1】:有一个错误:您需要ip = it->second.erase(ip);
。erase
使迭代器无效,并将迭代器返回到下一个元素。
但是你可以摆脱循环,让列表来完成工作:
else
it->second.remove_if([&f, &a](const Activity& act)
return act.getName() == a
&& act.getStartdate() == f; );
【讨论】:
是的,这解决了问题!【参考方案2】:您的代码存在分段错误,因为擦除使迭代器无效,但将迭代器返回到下一个元素。应该是:
ip = it->second.erase(ip);
前增量也比后增量更有效,因为不必存储原始值并复制迭代器:
++ip;
否则,如果您没有重复项,我会使用 std::set 而不是 std::list,这也应该更高效(日志而不是线性)。
#include <iostream>
#include <map>
#include <set>
std::map<const int, std::set<int>> map_set(0, 1, 2, 3, 4,
1, 10, 20, 30, 40,
2, 100, 200, 300, 400,
3, );
void delete_from_map_set(const int map_index, int value)
const auto & map_it = map_set.find(map_index);
if(map_it != map_set.end())
map_it->second.erase(value);
void print_map_set()
for(auto & map_it : map_set)
std::cout << map_it.first << ": [";
for(auto & list_it : map_it.second)
std::cout << list_it << ", ";
std::cout << "]" << std::endl;
int main(int argc, char * argv[])
print_map_set();
delete_from_map_set(0, 1);
print_map_set();
return 0;
【讨论】:
以上是关于从嵌套在 std::map 中的 std::list 中删除元素的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章