在C ++中将集合的前n个值复制到向量中的简便方法

问题描述

一个简单的问题,假设我保存了一个包含5个值的集合,并且想将前3个值复制到向量中,是否有一种快速简便的方法? 我知道,如果我想将整个集合复制到向量中,则可以使用如下代码

set <int> test = {0,1,2,3,4,5};
vector<int> vect(test.begin(),test.end());

我可以做一些类似于仅复制前n个值的操作吗?我一直在使用for循环来执行此操作,但我只是想检查是否有更快的编码方法

解决方法

要获得从n的{​​{1}}到begin的迭代器,std::set会产生所需的抽象。

std::next

这是由于std::vector<int> vec(test.cbegin(),std::next(test.cbegin(),5)); 提供了双向迭代器,因此您不能使用像std::set这样的算法。 test.cbegin() + 5为您解决了这个问题。

,

std::set::iterator是一个bidirectional迭代器,而不是random access迭代器,因此使用std::next`,如下所示

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

int main() {
    std::set <int> test = {0,1,2,3,4,5};
    size_t n=3;
    std::vector<int> vect;
    if(test.size() >= n) vect = std::vector<int>{test.begin(),std::next(test.begin(),n)};

    std::for_each(vect.begin(),vect.end(),[](auto el){std::cout << el <<" ";});
}

Demo

,

std::next()答案的问题在于std::next()本质上是不安全的。如果set中实际上没有5个元素,那么您将不断迭代结束迭代器,这是未定义的行为。

如果您改用range-v3,则这是一种安全且我认为更具表现力的解决方案:

auto vect = test
          | views::take(5)
          | ranges::to<std::vector>();

这将花费多达集合的前5个元素,并在结果范围之外构造vectorviews::take在C ++ 20中,但不幸的是ranges::to不是。

Demo