比较std :: list中的两个连续元素

时间:2022-08-25 02:17:21

I'd like to compare two consecutive elements in a std::list while iterating through the list. What is the proper way to access element i+1 while my iterator is at element i? Thanks Cobe

我想在迭代列表时比较std :: list中的两个连续元素。当我的迭代器在元素i时,访问元素i + 1的正确方法是什么?谢谢科贝

5 个解决方案

#1


11  

STL provide the adjacent_find() algorithm that can be used to find two consecutive equal elements. There is also a version with a custom predicate.

STL提供的adjacent_find()算法可用于查找两个连续的相等元素。还有一个带有自定义谓词的版本。

These are the prototypes:

这些是原型:

template <class ForwardIterator>
   ForwardIterator adjacent_find ( ForwardIterator first, ForwardIterator last );

template <class ForwardIterator, class BinaryPredicate>
   ForwardIterator adjacent_find ( ForwardIterator first, ForwardIterator last,
                                   BinaryPredicate pred );

#2


10  

Boost has a utility called next (and its inverse, prior) for just that purpose.

为了这个目的,Boost有一个名为next的实用程序(及其反向,先验)。

*itr == *next(itr)

Edit: But, if we step back to look at the forest, the real question is, why custom-write your adjacent_find function? (I recommend Nicola Bonelli's answer to be accepted.) That's part of the STL, and doesn't require using Boost, if your code doesn't use Boost (thanks to the commenters for pointing this out).

编辑:但是,如果我们回头看看森林,真正的问题是,为什么要自定义编写您的adjacent_find函数? (我建议Nicola Bonelli的答案被接受。)这是STL的一部分,如果您的代码不使用Boost,则不需要使用Boost(感谢评论者指出这一点)。

#3


8  

The simplest way would be to hold two iterators (since you'll have to stop at the penultimate one anyway).

最简单的方法是保持两个迭代器(因为你无论如何都必须停在倒数第二个)。

std::list<int>::const_iterator second = list.begin(),
                               end = list.end();

if ( second != end ) // Treat empty list
    for(std::list<int>::const_iterator first = second++; // Post-increment 
        second != end; 
        ++first, ++second)
    {
        //...
    }

Note that first is initialized with the post-incrementation of second so when the loop starts first is list.begin() and second is list.begin()+1.

请注意,首先使用第二个后递增来初始化,因此当循环首先开始时是list.begin(),第二个是list.begin()+ 1。

Chris Jester-Young points out that boost has next and prior functions, although I am not familiar with these functions (for my sins) implementing them is trivial (especially considering that list has bidirectional iterators).

Chris Jester-Young指出boost有下一个和前一个函数,虽然我不熟悉这些函数(对于我的罪),实现它们是微不足道的(特别是考虑到列表具有双向迭代器)。

template <class Iterator>
Iterator next(Iterator i) // Call by value, original is not changed
{ 
    return ++i;
}
// Implementing prior is left as an exercise to the reader ;o) 

My feeling is that use of next does not suite this problem as well as maintaining both iterators since you have to remember to make sure next(i) does not equal end() at every use.

我的感觉是使用next并不能解决这个问题以及维护两个迭代器,因为你必须记住确保next(i)在每次使用时都不等于end()。


Edits:

  • Fixed bug if the list is empty thanks to Luc Touraille's comment.
  • 修复了由于Luc Touraille的评论,如果列表为空的错误。

  • Add reference to next and why I think it doesn't fit this use-case.
  • 添加对next的引用以及为什么我认为它不适合这个用例。

#4


1  

List is a Reversible Container, so its iterators are Bidirectional Iterators, which is a model of Forward Iterator, which I'm pretty sure means you can do this (or something equivalent, if you're allergic to breaking out of the middle of a loop etc.):

List是一个可逆容器,因此它的迭代器是双向迭代器,它是Forward Iterator的模型,我很确定这意味着你可以做到这一点(或类似的东西,如果你对突破中间过敏)循环等):

if (!l.empty()) {
    for (list<T>::const_iterator i = l.begin();;) {
        const T &a = *i;
        ++i;
        if (i == l.end()) break;
        do_comparison(a, *i);
    }
}

You couldn't do that with an Input Iterator, because with those the values only "exist" as long as you have an iterator at them. But you can with a Forward Iterator.

你不能用Input Iterator做到这一点,因为只要你有一个迭代器,那些值只有“存在”。但你可以使用Forward Iterator。

#5


0  

for (list<int>::iterator it = test.begin(); it!=test.end(); it++) {
        cout<<*it<<":\t";
        list<int>::iterator copy = it;
        for( list<int>::iterator it2 =  ++copy; it2!=test.end();it2++){
            cout<<*it2<<"\t";
        }
        cout<<endl;
    }

#1


11  

STL provide the adjacent_find() algorithm that can be used to find two consecutive equal elements. There is also a version with a custom predicate.

STL提供的adjacent_find()算法可用于查找两个连续的相等元素。还有一个带有自定义谓词的版本。

These are the prototypes:

这些是原型:

template <class ForwardIterator>
   ForwardIterator adjacent_find ( ForwardIterator first, ForwardIterator last );

template <class ForwardIterator, class BinaryPredicate>
   ForwardIterator adjacent_find ( ForwardIterator first, ForwardIterator last,
                                   BinaryPredicate pred );

#2


10  

Boost has a utility called next (and its inverse, prior) for just that purpose.

为了这个目的,Boost有一个名为next的实用程序(及其反向,先验)。

*itr == *next(itr)

Edit: But, if we step back to look at the forest, the real question is, why custom-write your adjacent_find function? (I recommend Nicola Bonelli's answer to be accepted.) That's part of the STL, and doesn't require using Boost, if your code doesn't use Boost (thanks to the commenters for pointing this out).

编辑:但是,如果我们回头看看森林,真正的问题是,为什么要自定义编写您的adjacent_find函数? (我建议Nicola Bonelli的答案被接受。)这是STL的一部分,如果您的代码不使用Boost,则不需要使用Boost(感谢评论者指出这一点)。

#3


8  

The simplest way would be to hold two iterators (since you'll have to stop at the penultimate one anyway).

最简单的方法是保持两个迭代器(因为你无论如何都必须停在倒数第二个)。

std::list<int>::const_iterator second = list.begin(),
                               end = list.end();

if ( second != end ) // Treat empty list
    for(std::list<int>::const_iterator first = second++; // Post-increment 
        second != end; 
        ++first, ++second)
    {
        //...
    }

Note that first is initialized with the post-incrementation of second so when the loop starts first is list.begin() and second is list.begin()+1.

请注意,首先使用第二个后递增来初始化,因此当循环首先开始时是list.begin(),第二个是list.begin()+ 1。

Chris Jester-Young points out that boost has next and prior functions, although I am not familiar with these functions (for my sins) implementing them is trivial (especially considering that list has bidirectional iterators).

Chris Jester-Young指出boost有下一个和前一个函数,虽然我不熟悉这些函数(对于我的罪),实现它们是微不足道的(特别是考虑到列表具有双向迭代器)。

template <class Iterator>
Iterator next(Iterator i) // Call by value, original is not changed
{ 
    return ++i;
}
// Implementing prior is left as an exercise to the reader ;o) 

My feeling is that use of next does not suite this problem as well as maintaining both iterators since you have to remember to make sure next(i) does not equal end() at every use.

我的感觉是使用next并不能解决这个问题以及维护两个迭代器,因为你必须记住确保next(i)在每次使用时都不等于end()。


Edits:

  • Fixed bug if the list is empty thanks to Luc Touraille's comment.
  • 修复了由于Luc Touraille的评论,如果列表为空的错误。

  • Add reference to next and why I think it doesn't fit this use-case.
  • 添加对next的引用以及为什么我认为它不适合这个用例。

#4


1  

List is a Reversible Container, so its iterators are Bidirectional Iterators, which is a model of Forward Iterator, which I'm pretty sure means you can do this (or something equivalent, if you're allergic to breaking out of the middle of a loop etc.):

List是一个可逆容器,因此它的迭代器是双向迭代器,它是Forward Iterator的模型,我很确定这意味着你可以做到这一点(或类似的东西,如果你对突破中间过敏)循环等):

if (!l.empty()) {
    for (list<T>::const_iterator i = l.begin();;) {
        const T &a = *i;
        ++i;
        if (i == l.end()) break;
        do_comparison(a, *i);
    }
}

You couldn't do that with an Input Iterator, because with those the values only "exist" as long as you have an iterator at them. But you can with a Forward Iterator.

你不能用Input Iterator做到这一点,因为只要你有一个迭代器,那些值只有“存在”。但你可以使用Forward Iterator。

#5


0  

for (list<int>::iterator it = test.begin(); it!=test.end(); it++) {
        cout<<*it<<":\t";
        list<int>::iterator copy = it;
        for( list<int>::iterator it2 =  ++copy; it2!=test.end();it2++){
            cout<<*it2<<"\t";
        }
        cout<<endl;
    }