从嵌套在 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-&gt;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 中删除元素的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

使用 std::map 从数组中删除重复项

根据插入时间从std :: map中删除元素

VS2017 中嵌套循环的 OMP

std :: map中的最后一个键

std::map 中的内存分配

多线程中的 std::map 奇怪的资源争用