繁体   English   中英

通过 c++ 中的迭代器从向量中获取相邻的元素对

[英]Get adjacent pairs of elements from vector via iterator in c++

我想遍历向量中所有相邻的对元素。 例如,如果我有一个向量{1, 2, 3, 4} ,我希望我的迭代器返回以下内容:

(1, 2)
(2, 3)
(3, 4)

我知道如何使用以下方法一次迭代一个元素:

vector<int> numbers == {1, 2, 3, 4};
for (vector<int>::const_iterator it = numbers.cbegin(); 
     words != numbers.cend(); 
     ++it) 
{
    cout << *it << endl;
}

但我也不知道如何获得下一个元素。

Vector的迭代器是随机访问迭代器 您可以在迭代器上使用operator[]来获取下一个元素: it[1]

std::vector::iterator几乎可以像指针一样使用。

确保循环的条件被改变并在循环中使用*(it+1)

vector<int> numbers = {1, 2, 3, 4}; // One =, not two.

// If the vector is empty, skip the block.
if ( !numbers.empty() )
{
   vector<int>::const_iterator end = numbers.cend() - 1;

   for (vector<int>::const_iterator it = numbers.cbegin(); it != end; ++it) {
      cout << '(' << *it << ',' << *(it+1) << ')' << endl;
   }
}

工作演示

如果你需要使用std::vector这是一个使用迭代器是无意义的情况......使用索引的简单方法是

for (int i=0,n=numbers.size(); i<n-1; i++) {
    std::cout << '(' << numbers[i] << ", " << numbers[i+1] << ")\n";
}

当然它可以用迭代器完成,但它会很糟糕。

for (auto it = numbers.cbegin(); it != numbers.end() && std::next(it) != numbers.end(); ++it)
{
    cout << *it << " " << *std::next(it) << endl;

    // or, abusing C++17
    auto&& [first, second] = std::tie(*it, *std::next(it));
    cout << first << " " << second << endl;
}

如果你真的想要一个能够产生这对的迭代器,我会匆匆整理一个用于概念验证。 请注意,它没有经过广泛测试。

用法:

for (auto&& [first, second] : AdjacentRange{numbers})
{
    cout << first << " " << second << endl;
}

// or

for (auto&& pair : AdjacentRange{numbers})
{
    cout << pair.first << " " << pair.second << endl;
}

执行:

template <class It>
struct AdjancetRangeIt
{
    It it_;

    auto operator*() const
    {
        return std::tie(*it_, *std::next(it_));
    }

    auto operator++() -> auto& { ++it_; return *this; }
    auto operator!=(AdjancetRangeIt other) const { return it_ != other.it_; }
};

template <class It>
AdjancetRangeIt(It) -> AdjancetRangeIt<It>;

template <class It>
struct AdjacentRange
{
    It begin_, end_;

    template <class C>
    AdjacentRange(C& container)
        : begin_{std::begin(container)}, end_{std::end(container)}
    {}

    auto begin() const
    {
        return AdjancetRangeIt{begin_};
    }
    auto end() const
    {
        if (begin_ == end_)
            return AdjancetRangeIt{end_};
        else
            return AdjancetRangeIt{std::prev(end_)};
    }
};

template <class C>
AdjacentRange(C) -> AdjacentRange<typename C::iterator>;

您可以同时迭代两个元素:

std::vector<int> v{1,2,3,4};

for (auto l = v.begin(), r = l + 1, e = v.end(); r != e; ++l, ++r)
    std::cout << '(' << *l << ", " << *r << ")\n";

输出:

 (1, 2) (2, 3) (3, 4) 

Wandbox查看

显然,在即将到来的 C++23 中,您将能够使用 views::slide(2)。 例子:

vector<int> ints = {1, 2, 3, 4};
auto rg = ints | views::slide(2);
/*{{1, 2}, {2, 3}, {3, 4}}*/

auto [value1, value2] = (ints | views::slide(2))[0];
//value1=1
//value2=2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM