遍历c++11 std :: array的前N个元素

6
我正在使用std :: array(c++11)进行编程。我选择使用std :: array是因为我希望大小在编译时固定(而不是运行时)。有没有办法仅迭代前N个元素。例如:
std::array<int,6> myArray = {0,0,0,0,0,0};
std::find_if(myArray.begin(), myArray.begin() + 4, [](int x){return (x%2==1);});

这并不是最好的例子,因为find_if返回一个标记第一个奇数的迭代器,但您已经了解了这个想法(在这种情况下,我只想考虑我的std :: array的前N个元素,其中N = 4)。
注意:有类似于此问题的问题,但答案总是涉及使用不同的容器(vector或valarray),这不是我想要的。正如我早些时候描述的那样,我希望容器的大小在编译时固定。
提前感谢您!

2
你试过了吗? - DevSolar
我不确定我理解你的问题和目标,你想获取数组中前N个元素中的所有奇数吗?您可以使用std::transform 进行处理。否则,只需使用普通的 for 循环迭代 N 个元素即可。 - Some programmer dude
你不能把 std::find_if 放在一个函数里,其中 4 是一个参数吗? - TartanLlama
4
为什么你认为使用不同的容器会导致答案不同? - Jonathan Wakely
3个回答

2
从你提出问题的方式来看,我认为你是“迭代”这个词的意思,但实际上你想表达的是“使用算法操作”。
这种行为并不特定于容器,而是特定于容器的迭代器类型。
`std::array::iterator_type` 满足 `RandomAccessIterator`,与 `std::vector` 和 `std::deque` 相同。
这意味着,给定一个容器,无论它是什么类型的迭代器,都可以使用相同的算法来操作。
std::array<int,6> myArray = {0,0,0,0,0,0};

并且

auto end = myArray.begin() // ...

您可以将一个数字n加到它上面...
auto end = myArray.begin() + 4;

这段文本的意思是:导致迭代器指向数组中第n个元素之外的一个元素。由于这正是序列的“结束”迭代器的定义,所以它就是该迭代器的定义。
std::find_if(myArray.begin(), myArray.begin() + 4, ... )

很好地工作。下面是一个更加直观的例子:
#include <algorithm>
#include <array>
#include <iostream>

#define N 4

int main()
{
    std::array<char, 6> myArray = { 'a', 'b', 'c', 'd', 'e', 'f' };
    auto end = myArray.begin() + N;
    if ( std::find( myArray.begin(), end, 'd' ) != end )
    {
        std::cout << "Found.\n";
    }
    return 0;
}

这段代码会在数组中找到第四个元素,并输出“Found”。
如果将#define N 4改为#define N 3,则不会输出任何内容。
当然,前提是你的数组确实有N个元素。如果不确定,请先检查N <= myArray.size(),必要时使用myArray.end()
为了完整性:
  • 一个双向迭代器listsetmultisetmapmultimap)只支持++--
  • 一个前向迭代器forward_listunordered_setunordered_multisetunordered_mapunordered_multimap)只支持++
  • 一个输入迭代器不支持解引用后缀++的结果。

你能澄清一下你回答的是什么问题吗?再次阅读原帖,我不明白这个回答如何解答他的问题。(这是一个好的、有见地的回答,但不确定它回答了哪个“问题”!)。另外,使用#define定义常量很可能应该避免。 - user1781434
你为什么要使用 std::find ...? - user1781434
@Tobias:因为它接近于原帖的示例,但比他的lambda更简单易验证。(我假设OP “迭代”,但由于他给出的示例和相关文本,意思是“使用算法操作”) - DevSolar
只有当数组的大小至少为N时,使用例如myArray.begin() + N才有效,否则它将超出myArray.end() - Some programmer dude
1
@JoachimPileborg: 叹气 这就是为什么我们不能拥有好东西。;-) 在答案中添加了一条注释。 - DevSolar
显示剩余5条评论

0
如果您想迭代一个 std::array 的前 N 个数字,只需执行以下操作:
#include <iostream>
#include <array>

int main() {
    constexpr const int N = 4;
    std::array<int, 6> arr{ 0, 1, 2, 3, 4, 5 };
    for (auto it = std::begin(arr); it != std::begin(arr) + N && it != std::end(arr); ++it)
        std::cout << *it << std::endl;
}

0

在C++20中,可以使用std::span来创建std::array的子集视图,就像std::string_view对于std::string一样。该span替代了维护子元素数量变量“N”的操作。

auto part = std::span(myArray).first(4);

std::find_if(part.begin(), part.end(), [](int x) {return (x % 2 == 1); });

一个 std::span 提供了许多其他好处。它可以在基于范围的 for 循环中使用。通过使用 std::span.subspan,span 可以查看任何元素的范围,不仅限于前 N 个。span 还可以不仅用于 std::array,还可以用于 C 数组、 std::vector 和其他连续容器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接