2008-11-04 34 views
5

Tôi muốn so sánh hai phần tử liên tiếp trong danh sách std :: khi đang lặp qua danh sách. Cách thích hợp để truy cập phần tử i + 1 trong khi trình vòng lặp của tôi là ở phần tử i là gì? Cảm ơn CobeSo sánh hai phần tử liên tiếp trong tiêu chuẩn: danh sách

+0

Nếu có thể bạn có thể muốn thay đổi tiêu đề câu hỏi thành "Làm cách nào để so sánh HAI phần tử liên tiếp trong std :: list?". Tôi muốn tự mình làm điều đó, nhưng không có danh tiếng ;-) –

Trả lời

10

Boost có tiện ích gọi là next (và ngược lại, prior) chỉ nhằm mục đích đó.

*itr == *next(itr) 

Edit: Nhưng, nếu chúng ta lùi lại để nhìn vào rừng, thực câu hỏi là, tại sao tùy chỉnh-viết hàm adjacent_find của bạn? (Tôi đề nghị câu trả lời của Nicola Bonelli để được chấp nhận.) Đó là một phần của STL, và không yêu cầu sử dụng Boost, nếu mã của bạn không sử dụng Boost (nhờ những người bình luận để chỉ ra điều này).

+0

Thật thú vị khi gần như mọi câu hỏi C++ trên trang web đã hoàn toàn khác "nếu bạn có Boost" và "nếu bạn giới hạn đến các câu trả lời chuẩn C++". Hầu như là các ngôn ngữ khác nhau ... –

+0

Tôi đã suy nghĩ cùng một điều :) – warren

+0

Nó _is_ giống như các ngôn ngữ khác nhau! Boost là những gì làm cho C++ có giá trị sử dụng, với tôi. :-P Không sử dụng Boost giống như không sử dụng SRFI khi viết mã Scheme. :-P –

8

Cách đơn giản nhất là giữ hai trình lặp (vì bạn sẽ phải dừng lại ở áp chót).

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) 
    { 
     //... 
    } 

Lưu ý rằng first được khởi tạo với các post-incrementation của second vì vậy khi vòng lặp bắt đầu firstlist.begin() và thứ hai là list.begin()+1.

Chris Jester-Young points out rằng thúc đẩy có nextprior chức năng, mặc dù tôi không quen thuộc với các chức năng (đối với tội lỗi của tôi) thực hiện chúng là tầm thường (đặc biệt là xem xét rằng list có lặp hai chiều).

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) 

Cảm giác của tôi là sử dụng next không phù hợp với vấn đề này cũng như việc duy trì cả hai lặp kể từ khi bạn phải nhớ để đảm bảo next(i) không bằng end() tại mỗi lần sử dụng.


Chỉnh sửa:

  • Sửa lỗi nếu danh sách này là nhờ có sản phẩm nào để bình luận Luc Touraille 's.
  • Thêm tham chiếu đến next và lý do tôi cho rằng nó không phù hợp với trường hợp sử dụng này.
+0

Rất tiếc sau khi viết thực hiện tiếp theo, tôi thấy rằng nó chính xác giống như trong liên kết Chris được bao gồm trong bài đăng hi. – Motti

+0

Ahh, sức mạnh của các giải pháp đơn giản, rõ ràng! :-P Tôi vẫn nghĩ liền kề_find là giải pháp đơn giản nhất của lô hàng, nhưng có. –

10

STL cung cấp thuật toán lân cận() có thể được sử dụng để tìm hai phần tử bằng nhau. Ngoài ra còn có một phiên bản với một vị từ tùy chỉnh.

Đây là những nguyên mẫu:

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

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

Bạn là câu trả lời tôi ước tôi đã tự viết; Tôi hy vọng OP chấp nhận câu trả lời của bạn. Đồ tốt! +1 (tôi sẽ +5, nhưng trang web không cho phép điều đó) –

1

Danh sách là một Reversible container, do đó vòng lặp của nó là vòng lặp hai chiều, mà là một mô hình của Forward Iterator, mà tôi chắc rằng có nghĩa là bạn có thể làm điều này (hoặc một cái gì đó tương đương, nếu bạn bị dị ứng để phá vỡ giữa một vòng lặp vv):

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); 
    } 
} 

Bạn không thể làm điều đó với một Iterator đầu vào, bởi vì với những giá trị chỉ "tồn tại" lâu khi bạn có một trình lặp vào chúng. Nhưng bạn có thể với một Iterator Chuyển tiếp.

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; 
    } 
Các vấn đề liên quan