在向量中查找映射键的最快方法

时间:2018-05-21 17:26:04

标签: c++ performance optimization stdvector unordered-map

我正在寻找更快的方法来提取由矢量键过滤的地图值。

标准代码下方:

    std::unordered_map<uint32, user> map;
    std::vector<uint32> to_find; 
    std::vector<user> results;

    auto it = map.begin();

    while (it != map.end())
    {
        if (std::find(to_find.begin(), to_find.end(), it->first) == to_find.end())
            results.push_back(it->second);
        it++;
    }

2 个答案:

答案 0 :(得分:0)

您可以使用std::binary_search(),其时间复杂度为 O(log n),其中n是向量to_find的大小。这可能比使用具有线性时间复杂度的std::find()要好得多。

DEMO

#include <algorithm>
#include <iostream>
#include <vector>
#include <unordered_map>

using user = int;
using uint32 = unsigned long int;

int main()
{
    std::unordered_map<uint32, user> myMap = {{1,2},{3,5},{2,9},{4,7}};
    std::vector<uint32> to_find = {1,3};
    std::vector<user> results;

    if(to_find.size() == 0)  // if you have to_find vec size = 0
        std::for_each(myMap.cbegin(), myMap.cend(), [&results](const auto& ele)->void
                                                    {
                                                        results.emplace_back(ele.second);
                                                    });
    else
    {
        for(const auto& it: myMap)// binary_search; if not found add the value
            if(!std::binary_search(to_find.begin(), to_find.end(), it.first))
                results.emplace_back(it.second);
    }

    for(const auto& it: results) std::cout << it << std::endl;
}

答案 1 :(得分:0)

如果您的容器都已排序,则线性方式是使用类似于std::merge的算法:

template <typename KEY, typename VALUE>
std::vector<VALUE>
collect_absents(const std::map<KEY, VALUE>& map, const std::vector<KEY>& present)
{
    std::vector<VALUE> res;

    auto mit = map.begin();
    auto vit = present.begin();

    while (mit != map.end() && vit != present.end())
    {
        if (*vit < mit->first) {
            ++vit;   
        } else if (mit->first < *vit) {
            res.push_back(mit->second);
            ++mit;   
        } else { // equal
            ++vit;
            ++mit;
        }
    }
    for (; mit != map.end(); ++mit) {
        res.push_back(mit->second);
    }
    return res;
}

Demo