一个衬垫用于插入类对象的某些特定值

use*_*448 9 c++ std set c++14 c++17

假设我有一个vector<int> myVec;,我想把它转换成一套,我可以有一个班轮 -

set<int> mySet(myVec.begin(), myVec.end());
Run Code Online (Sandbox Code Playgroud)

这是可以轻松找到的东西.

现在我有vector<pair<int, int>>,并且我想获得每对中的第二个值的集合.我应该如何使用set构造函数来实现这一目标?可能吗?

假设我有C++ 11,C++ 14,C++ 17.

另外,如果我能获得一些关于如何针对不同容器进行类似调整的一般意义的信息,我将不胜感激.

lub*_*bgr 16

在这种情况下要求单线程不可避免地导致范围-v3的解决方案:

#include <range/v3/view/map.hpp>

const std::vector<std::pair<int, int>> myVec{{1, 10}, {2, 20} , {3, 30}};
const std::set<int> mySet = myVec | ranges::view::values;
Run Code Online (Sandbox Code Playgroud)

Boost范围 ¹ 类似的方法:

#include <boost/range/adaptor/map.hpp>

using boost::adaptors::map_values;
const auto mySet = boost::copy_range<std::set<int>>(myVec | map_values); 
Run Code Online (Sandbox Code Playgroud)

您可能认为这种方法最简单,但是(没有库,但需要C++ 17):

for (const auto& [first, second] : myVec)
    mySet.insert(second);
Run Code Online (Sandbox Code Playgroud)

¹感谢@Caleth建议改进评论.

  • 这太棒了.范围API非常酷,我希望它能很快达到标准. (2认同)

jde*_*esa 6

这几乎是一个班轮应该适合你:

#include <algorithm>
#include <iterator>
#include <iostream>
#include <set>
#include <utility>
#include <vector>

int main()
{
    std::vector<std::pair<int, int>> myVec = { {1, 2}, {3, 4} };
    std::set<int> mySet;
    std::transform(myVec.begin(), myVec.end(), std::inserter(mySet, mySet.begin()),
                   [](const std::pair<int, int>& elem) { return elem.second; });
    for (int value : mySet)
    {
        std::cout << value << std::endl;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

2
4
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,使用`transform`的"单行"比等效的for-loop/insert要长得多.假设正常间距和带结构化绑定的全名... 143个字符对69. (5认同)
  • 我认为这是最好的你可以使用标准的C++,但这仍然不是一个单行 (2认同)

Joh*_*nck 5

最常用的C++方法可能是定义一个只产生第二个值的自定义迭代器类型.

您可以使用与更常见查询非常相似的代码,即从map:iterator适配器中获取值以仅迭代映射中的值?

或者,你知道,只需写一个循环.没有错.