Sch*_*tky 25 c++ stl std stdvector std-pair
我有一个偶数大小的向量,我想将其转换为成对的向量,其中每对始终包含两个元素。我知道我可以使用简单的循环来做到这一点,但我想知道是否有一个很好的标准库工具可以做到这一点?可以假设原始向量始终包含偶数个元素。
例子:
vector<int> origin {1, 2, 3, 4, 5, 6, 7, 8};
vector<pair<int, int>> goal { {1, 2}, {3, 4}, {5, 6}, {7, 8} };
Run Code Online (Sandbox Code Playgroud)
Enr*_*lis 21
使用范围-v3:
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/chunk.hpp>
using namespace ranges;
using namespace ranges::views;
int main() {
std::vector<int> origin {1, 2, 3, 4, 5, 6, 7, 8};
std::vector<std::pair<int, int>> goal {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
auto constexpr makePairFromRangeOf2 = [](auto two){
return std::make_pair(two.front(), two.back());
};
auto result = origin | chunk(2)
| transform(makePairFromRangeOf2)
| to_vector;
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果您只需循环 on result,那么您只需要它是一个范围,因此您可以省略| to_vector,因为您仍然可以执行result.begin()and result.end(),这就是result范围的组成部分。
如果您不需要内部容器真正成为std::pairs,但您只是对调用感到满意,比如说,result.front().front()而不是result.front().first,那么您也可以离开transform,并且对 感到满意auto result = origin | chunk(2);。
您没有提到为什么您只想要一个标准解决方案。但是请考虑这<ranges> 是C++20 中的标准。不幸的是,该功能不如 C++20 Range-v3 之前的库强大。但我认为毫无疑问,它会在某个时刻(C++23?)。
ein*_*ica 13
正如 @\xe5\xba\xb7\xe6\xa1\x93\xe7\x91\x8b 提到的,如果您还愿意使用ranges-v3库,您可以使用视图chunk():
std::vector origin = {1, 2, 3, 4, 5, 6, 7, 8};\nauto goal = origin | ranges::views::chunk(2) | ranges::to<std::vector>;\nRun Code Online (Sandbox Code Playgroud)\n看到它正在运行GodBolt。
\n与我的其他答案不同,这在语言方面是完全有效的。
\n注意事项:
\nchunk()将to()在 C++23 中,因此只要稍作语法调整(例如添加std::),这将是仅包含标准库的有效 C++23。goal不是std::pairs,而是范围。您将需要获取第一个和第二个元素,或者第一个和最后一个元素来形成实际的对。我有一个处理向量中偶数和奇数元素的函数。它的作用是需要另一个参数在对的末尾添加一个数字。我认为截至目前还没有任何标准工具/库可以这样做C++ 20,有一个Range-v3库C++ 23尚未发布。
这是在线尝试链接。
#include <iostream>
#include <vector>
// time complexity: O(n / 2), where `n` is the length of `my_vec`
std::vector<std::pair<int, int>> vec_to_pair(const std::vector<int> &my_vec, int odd_origin)
{
std::vector<std::pair<int, int>> val;
for (std::size_t i = 0; i < my_vec.size(); i += 2)
{
int sec_val;
if (i < my_vec.size() - 1)
sec_val = my_vec[i + 1];
else if (my_vec.size() % 2 != 0)
sec_val = odd_origin;
else
break;
int data[] = {my_vec[i], sec_val};
val.push_back({data[0], data[1]});
}
return val;
}
void print(const std::vector<std::pair<int, int>> &vec)
{
std::cout << "{ ";
for (auto &&i : vec)
std::cout << "{ " << i.first << ", " << i.second << " } ";
std::cout << " }" << std::endl;
}
int main(void)
{
std::vector<int> vec1 = {1, 2, 3, 4, 5}; // odd
std::vector<int> vec2 = {1, 2, 3, 4, 5, 6}; // even
auto x1 = vec_to_pair(vec1, -1);
auto x2 = vec_to_pair(vec2, 0);
print(x1);
print(x2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)