用C++切片向量

Wiz*_*ard 10 c++ vector

[1:]在C++中有没有相当于Python 的列表切片与向量?我只想从矢量中获取除第一个元素之外的所有元素.

Python的列表切片运算符:

list1 = [1, 2, 3]
list2 = list1[1:]  

print(list2) # [2, 3]
Run Code Online (Sandbox Code Playgroud)

C++期望的结果:

std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2;
v2 = v1[1:];

std::cout << v2 << std::endl;  //{2, 3}
Run Code Online (Sandbox Code Playgroud)

mne*_*rco 16

在 C++20 中这非常简单:

#include <span>
#include <vector>
#include <iostream>

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



int main()
{
    std::vector v{1,2,3,4,5,6,7,8,9};

    std::cout << "-------------------" << std::endl;
    auto v0 = slice<1,0>(v);
    for (auto i : v0)
    {
        std::cout << i << std::endl;
    }

    std::cout << "-------------------" << std::endl;
    auto v1 = slice<0,-1>(v);
    for (auto i : v1)
    {
        std::cout << i << std::endl;
    }

    std::cout << "-------------------" << std::endl;
    auto v2 = slice<1,3>(v);
    for (auto i : v2)
    {
        std::cout << i << std::endl;
    }

    std::cout << "-------------------" << std::endl;
    auto v3 = slice<1,-1>(v);
    for (auto i : v3)
    {
        std::cout << i << std::endl;
    }

    std::cout << "-------------------" << std::endl;
    auto v4 = slice<3,3>(v);
    for (auto i : v4)
    {
        std::cout << i << std::endl;
    }

}
Run Code Online (Sandbox Code Playgroud)

结果:

Program returned: 0
-------------------
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
-------------------
Run Code Online (Sandbox Code Playgroud)

您还可以添加边界检查和其他情况,例如负左索引等......但这只是一个示例。

在编译器资源管理器中运行:https ://godbolt.org/z/qeaxvjdbj

  • std::slice 没问题,但我正在尝试类似于 std::vector 的 python 语法。据我了解 std::slice 不适用于 std::vector。(之前的评论已被删减) (2认同)

Dim*_*htz 15

这可以使用std::vector构造函数之一轻松完成:

v2 = std::vector<int>(v1.begin() + 1, v1.end());
Run Code Online (Sandbox Code Playgroud)

  • 我知道确实如此,我只是建议将其包含在答案中以使其完美无缺。 (6认同)
  • 提及是否包含`v1.end()`,可以改善此答案。 (5认同)
  • @AlessandroFlati 是的,确实如此。否则我的答案将是错误的,因为OP问:“我只想从向量中获取除第一个元素之外的所有元素”:) (3认同)
  • 只是为了记录,“v1.end()”不是向量末尾的元素,它是指向最后一个元素之后的(不存在的)元素的迭代器。 (3认同)

xsk*_*xzr 12

这取决于您想要查看还是副本。

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

list1 = [1, 2, 3]
list2 = list1[1:]  
list2[1] = 5
print(list1) # does not change, still [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
list1 = [1, 2, [3]]
list2 = list1[1:]  
list2[1][0] = 5
print(list1) # changes, becomes [1, 2, [5]]
Run Code Online (Sandbox Code Playgroud)

请参阅这篇文章了解详细信息。

DimChtz 的回答模拟了复制情况。如果你只想要一个视图,在 C++20 中,你可以使用范围(除了std::views::drop,std::views::takestd::views::counted也很有用):

auto v2 = v1 | std::views::drop(1); // #include <ranges>
for (auto &e: v2) std::cout << e << '\n';  
Run Code Online (Sandbox Code Playgroud)

或者std::span

std::span v2{v1.begin() + 1, v1.end()}; // #include <span>
for (auto &e: v2) std::cout << e << '\n';  
Run Code Online (Sandbox Code Playgroud)


Adr*_*ian 5

我知道已经晚了,但看看valarray它的slices。如果您正在使用某种类型的向量NumericType,那么值得一试。