在C++中切片一个向量

8 浏览
0 Comments

在C++中切片一个向量

在C++中有没有类似于Python中用于列表切片的[1:]的等效方法?我只是想从一个向量中获取除第一个元素以外的所有元素。\nPython的列表切片操作符:\n

list1 = [1, 2, 3]
list2 = list1[1:]  
print(list2) # [2, 3]

\nC++期望的结果:\n

std::vector v1 = {1, 2, 3};
std::vector v2;
v2 = v1[1:];
std::cout << v2 << std::endl;  //{2, 3}

0
0 Comments

在C++中切片一个向量的问题的出现是因为需要确定是要一个视图(view)还是一个副本(copy)。

Python中对于列表的切片会复制元素的引用,因此不能简单地将其视为视图或副本。例如:

list1 = [1, 2, 3]
list2 = list1[1:]
list2[1] = 5
print(list1)  # 输出不变,仍然是[1, 2, 3]

list1 = [1, 2, [3]]
list2 = list1[1:]
list2[1][0] = 5
print(list1)  # 输出改变,变成[1, 2, [5]]

详情请参考[这个帖子](https://stackoverflow.com/a/5131563/5376789)。

[DimChtz的回答](https://stackoverflow.com/a/50549636/5376789)模拟了复制的情况。如果你只想要一个视图,在C++20中,你可以使用[ranges](https://en.cppreference.com/w/cpp/ranges)(除了[std::views::drop](https://en.cppreference.com/w/cpp/ranges/drop_view)、[std::views::take](https://en.cppreference.com/w/cpp/ranges/take_view)和[std::views::counted](https://en.cppreference.com/w/cpp/ranges/view_counted)之外):

auto v2 = v1 | std::views::drop(1);  // 需要包含
for (auto &e: v2) std::cout << e << '\n';

或者使用[std::span](https://en.cppreference.com/w/cpp/container/span):

std::span v2{v1.begin() + 1, v1.end()};  // 需要包含
for (auto &e: v2) std::cout << e << '\n';

还可以使用带有span的`std::span::subspan()`方法。不过它不支持负索引。

0
0 Comments

C++20中提供了一种简单的方法来切片向量(Slicing a vector)。上述代码使用了C++20的新特性,展示了如何使用切片语法对向量进行切片操作。

切片函数的代码如下所示:

#include 
#include 
#include 
template
constexpr auto slice(T&& container)
{
    if constexpr (right > 0)
    {
        return std::span(begin(std::forward(container))+left, begin(std::forward(container))+right);
    }
    else
    {
        return std::span(begin(std::forward(container))+left, end(std::forward(container))+right);
    }
}

在主函数中,通过调用切片函数对向量进行切片操作,并输出结果。

通过运行上述代码,可以得到以下结果:

-------------------
2
3
4
5
6
7
8
9
-------------------
1
2
3
4
5
6
7
8
-------------------
2
3
-------------------
2
3
4
5
6
7
8
-------------------

上述代码展示了如何使用切片语法对向量进行切片操作,通过指定左边界和右边界来选择切片的范围。切片函数支持正向和反向索引,可以灵活地对向量进行切片。

这种切片语法非常酷,但为什么不使用`std::slice`呢?

`std::slice`也可以实现切片操作,但我想尝试一种类似Python中对`std::vector`使用切片语法的方式。据我了解,`std::slice`不适用于`std::vector`。

总之,通过使用C++20的新特性,我们可以很方便地对向量进行切片操作,提供了一种更简洁和直观的语法来处理向量的子集。

0
0 Comments

Slicing a vector in C++

在C++中切片一个向量是非常简单的,可以使用std::vector的拷贝构造函数来完成。代码如下:

v2 = std::vector<int>(v1.begin() + 1, v1.end());

然而,这个答案还可以改进,需要明确是否包含v1.end()这个元素。于是有人提出了问题:v2中是否包含v1中的最后一个元素?

答案是肯定的,v2中确实包含v1的最后一个元素。否则,答案就是错误的,因为提问者要求的是从向量中获取除第一个元素之外的所有元素。

还有一个人提到了要把这个信息加入到答案中,以使其更加完整。

需要说明的是,v1.end()并不指向向量的最后一个元素,而是指向最后一个元素之后(不存在的)一个元素的迭代器。

时间复杂度是O(size of sliced vector)

请移除最后一句话,正如前面所提到的,v1.end()并不指向向量的最后一个元素,因此v2中不包含v1.end()。

0