我的unordered_map看起来像这样:
std::unordered_map<int, std::string> theMap2 = {{1,"a"}, {2,"b"}, {3,"c"}, {4,"a"}};
我想找到所有具有相同值的键让我们说“a”。除了显而易见的方式之外的任何建议:
std::vector<int> arrKeys;
std::string value = "a";
for (const auto& element : theMap)
if (element.second == value)
arrKeys.push_back(element.first);
答案 0 :(得分:9)
我认为“显而易见”的方式非常好:它简单,简洁,易于阅读。
另一种选择是使用stl算法。您需要的是transform_if
算法,因此您可以说:
std::transform_if(std::begin(theMap), std::end(theMap), std::back_inserter(arrKeys), check_value, get_value);
但在stl中没有这样的。我可以建议的是:
std::vector<int> arrKeys;
std::string value = "a";
auto check_value = [&](std::pair<const int, std::string> const& p)->bool
{
return (p.second == value);
};
auto end = std::end(theMap);
auto it = find_if(std::begin(theMap), end, check_value);
while (it != end)
{
arrKeys.push_back(it->first);
it = find_if(std::next(it), end, check_value);
}
答案 1 :(得分:2)
更多的是出于兴趣而不是其他任何东西,我写了一个可用于copy_if
的基本包装器。它类似于std::back_inserter
,但它不是仅插入给定的对象,而是插入std::get<N>(obj)
。这使其可用于std::array
,std::tuple
和std::pair
。
要在此示例中插入pair.first
,我们使用back_n_inserter<0>
。
template< std::size_t N, class Container >
class back_n_insert_iterator : public std::iterator< std::output_iterator_tag,
void, void, void, void >
{
public:
back_n_insert_iterator (Container& c) : c{c} {};
//could protect this by checking that the get call is_convertible to the value_type
template <typename T>
decltype(auto) operator= (T&& collec)
{
c.push_back(std::get<N>(std::forward<T>(collec)));
return *this;
}
decltype(auto) operator* () { return *this; }
decltype(auto) operator++ () { return *this; }
decltype(auto) operator++ (int) { return *this; }
private:
Container& c;
};
template< std::size_t N, class Container >
back_n_insert_iterator<N,Container> back_n_inserter( Container& c )
{
return {c};
}
现在我们可以在copy_if
电话中使用我们的适配器:
std::copy_if(theMap.begin(), theMap.end(),
back_n_inserter<0>(arrKeys),
[&value](const auto& el){return el.second == value;});
感谢@dyp提供所有建议。