boost中unorder_set使用

3 篇文章 0 订阅

背景

遍历一个大文件中行数据,将有版权的信息和无版权的信息按照name1+name2这个组合关键字分开,分别记为集合Set1和Set2。如果无版权信息name1+name2信息集合(Set2)中出现在Set1中则将该关键字对应的数据从该Set1集合中删除,即视为该关键字name1+name2是有版权的。

方案分析:

逐行遍历,将每行有版权和无版权的信息分别存放于unordered_set 中的set1和set2中。遍历结束之后,此时的set1和set2中自身已经是经过name1+name2关键字去重的,所以只需要将set1和set2的交集,从set1中去除。
对于unordered_set 可以选择使用STL中的,至于STL版,C11中的STL才有unordered_set
否则会报错:

‘unordered_set’ is not a member of ‘std’

所以请预先注意这点。
对于unordered_set的遍历
对于stl中的,支持auto变量
可以用以下的方法:

std::unordered_set<T> mySet;
for (const auto& elem: mySet) {
    /* ... process elem ... */
}

也可以通过迭代器的方式遍历:

std::unordered_set<T> mySet;
for (auto itr = mySet.begin(); itr != mySet.end(); ++itr) {
    /* ... process *itr ... */
    std::cout << (*itr) << std::endl;
}

或者:

std::unordered_set<T> mySet;
for (std::unordered_set<T>::iterator itr = mySet.begin(); itr != mySet.end(); ++itr) {
    /* ... process *itr ... */
}

也可以使用boost中的unordered_set。本文主要介绍boost下的使用情况。

boost版:

注意boost中的erase操作的返回结果,否则可能将导致loop循环仅仅erase一个结果就使得迭代器为end,从而跳出整个循环,进而使结果仅删除一个元素。
如下代码所展示的:

   boost::unordered_set<std::string> myhashset;
    myhashset.insert("A1");
    myhashset.insert("A2");
    myhashset.insert("A2");
    myhashset.insert("A3");
    myhashset.insert("A4");
    std::cout<<"set1 size="<<myhashset.size()<<std::endl;
    boost::unordered_set<std::string> myhashset2;
    myhashset2.insert("A1");
    myhashset2.insert("A2");
    myhashset2.insert("A3");
    myhashset2.insert("B2");
    myhashset2.insert("B3");
    //find 操作
    std::cout << (myhashset.find("ABCA1") != myhashset.end()) << std::endl;
    std::cout << (myhashset.find("A2") != myhashset.end()) << std::endl;


    boost::unordered_set<std::string>::iterator ib;
    boost::unordered_set<std::string>::iterator ib2;
    for (ib = myhashset.begin(); ib != myhashset.end();ib++)
    {
        std::cout << *ib << std::endl;//
    }
    //去重
    for (ib = myhashset.begin(); ib != myhashset.end();++ib)//set是变化的,随时其中元素被删除
    {
        if(myhashset2.find(*ib) != myhashset2.end())
        {
            std::cout<<"need to delete:"<< *ib << std::endl;
            myhashset.erase(ib);//删除完之后,此时的iter指针ib位于end位置??
            std::cout<<"now ib="<<*ib<<std::endl;//删除之后此时的*ib指向是空的,所以ib被强制修改了
            std::cout<<"myhashset size:"<<myhashset.size()<<std::endl;
            boost::unordered_set<std::string>::iterator ib1;
            ib1 = myhashset.begin();
            std::cout<<"myhashset first:"<<*ib1<<std::endl;
        }
    }

运行结果:
这里写图片描述
从上述的运行结果可以看出,在erase操作之后,*ib值是空。导致for循环直接跳出,所以整个过程仅仅是去掉了A3,而预期中的A2,A1被跳过。

我们需要注意的是erase调用之后的返回值,文档如下:
Returns:
The iterator following position before the erasure.
Throws:
Only throws an exception if it is thrown by hasher or key_equal.
Notes:
In older versions this could be inefficient because it had to search through several buckets to find the position of the returned iterator. The data structure has been changed so that this is no longer the case, and the alternative erase methods have been deprecated.

代码修改:

    boost::unordered_set<std::string> myhashset;
    myhashset.insert("A1");
    myhashset.insert("A2");
    myhashset.insert("A2");
    myhashset.insert("A3");
    myhashset.insert("A4");
    std::cout<<"set1 size="<<myhashset.size()<<std::endl;
    boost::unordered_set<std::string> myhashset2;
    myhashset2.insert("A1");
    myhashset2.insert("A2");
    myhashset2.insert("A3");
    myhashset2.insert("B2");
    myhashset2.insert("B3");
    //find 操作
    // std::cout << (myhashset.find("ABCA1") != myhashset.end()) << std::endl;
    // std::cout << (myhashset.find("A2") != myhashset.end()) << std::endl;


    boost::unordered_set<std::string>::iterator ib;
    boost::unordered_set<std::string>::iterator ib2;
    for (ib = myhashset.begin(); ib != myhashset.end();ib++)
    {
        std::cout << *ib << std::endl;//
    }
    //去重
    for (ib = myhashset.begin(); ib != myhashset.end();)//set是变化的,随时其中元素被删除
    {
        if(myhashset2.find(*ib) != myhashset2.end())
        {
            string temp = *ib;
            ib = myhashset.erase(ib);//删除完之后,此时的iter指针ib位于end位置??
            // std::cout<<"now ib="<<*ib<<std::endl;//删除之后此时的*ib指向是空的,所以ib被强制修改了
            std::cout<<"after eraser:"<<temp<<",myhashset size:"<<myhashset.size()<<std::endl;
            boost::unordered_set<std::string>::iterator ib1;
            //
            std::cout<<"after eraser:"<<temp<<",new set:"<< std::endl;
             for (ib1 = myhashset.begin(); ib1 != myhashset.end();ib1++)
            {
                std::cout << *ib1 << std::endl;
            }
        }
        else
        {
            ++ib;
        }
    }
    std::cout<<"method 1,after erase the data:"<<std::endl;
    for (ib = myhashset.begin(); ib != myhashset.end();ib++)
    {
        std::cout << *ib << std::endl;
    }

运行结果如下:
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值