Iteracja wektora C++ od końca do początku

Czy możliwe jest iterację wektora od końca do początku?

for (vector<my_class>::iterator i = my_vector.end();
        i != my_vector.begin(); /* ?! */ ) {
}

Czy jest to możliwe tylko z czymś takim:

for (int i = my_vector.size() - 1; i >= 0; --i) {
}
Author: Daniel Daranas, 2010-08-31

7 answers

Cóż, najlepszym sposobem jest:

for (vector<my_class>::reverse_iterator i = my_vector.rbegin(); 
        i != my_vector.rend(); ++i ) { 
} 

Rbegin () / rend () (I tak, zwiększenie odwrotności_interator przesuwa go do tyłu)

Teraz, w teorii, twoja metoda (używając begin/end & --i) będzie działać, iterator Vectora będzie dwukierunkowy, ale pamiętaj, end() nie jest ostatnim elementem - jest jednym poza ostatnim elementem, więc będziesz musiał najpierw dekrementować i skończysz, gdy osiągniesz begin () - ale nadal musisz wykonać swoje przetwarzanie.

vector<my_class>::iterator i = my_vector.end();
while (i != my_vector.begin())
{
     --i;
    /*do stuff */ ) 

} 

UPDATE: najwyraźniej zbyt agresywnie pisałem pętlę for () na pętlę while. (Ważną częścią jest to, że --i jest na początku.)

 89
Author: James Curran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-31 18:50:45

Jeśli masz C++11, możesz skorzystać z auto.

for (auto it = my_vector.rbegin(); it != my_vector.rend(); ++it)
{
}
 25
Author: Akavall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-20 15:06:25

Dobrze ugruntowany "wzorzec" dla odwrotnej iteracji przez zakresy Zamknięte-Otwarte wygląda następująco

// Iterate over [begin, end) range in reverse
for (iterator = end; iterator-- != begin; ) {
  // Process `*iterator`
}

Lub, jeśli wolisz,

// Iterate over [begin, end) range in reverse
for (iterator = end; iterator != begin; ) {
  --iterator;
  // Process `*iterator`
}

Ten wzorzec jest użyteczny, na przykład do indeksowania odwrotnego tablicy przy użyciu indeksu niepodpisanego

int array[N];
...
// Iterate over [0, N) range in reverse
for (unsigned i = N; i-- != 0; ) {
  array[i]; // <- process it
}

(osoby nie znające tego wzorca często nalegają na używanie signed integer types do indeksowania tablic, ponieważ błędnie uważają, że niepodpisane typy zapobiegają indeksowaniu odwrotnemu)

Może być używany do iteracji na tablicy przy użyciu techniki "sliding pointer"

// Iterate over [array, array + N) range in reverse
for (int *p = array + N; p-- != array; ) {
  *p; // <- process it
}
Może być również użyty do iteracji odwrotnej nad wektorem za pomocą zwykłego (Nie odwrotnego) iteratora
for (vector<my_class>::iterator i = my_vector.end(); i-- != my_vector.begin(); ) {
  *i; // <- process it
}
 15
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-31 17:56:55

User rend() / rbegin() Iteratory:

for (vector<myclass>::reverse_iterator it = myvector.rbegin(); it != myvector.rend(); it++)

 7
Author: a1ex07,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-31 16:10:31
template<class It>
std::reverse_iterator<It> reversed( It it ) {
  return std::reverse_iterator<It>(std::forward<It>(it));
}

Wtedy:

for( auto rit = reversed(data.end()); rit != reversed(data.begin()); ++rit ) {
  std::cout << *rit;

Alternatywnie w C++14 wystarczy zrobić:

for( auto rit = std::rbegin(data); rit != std::rend(data); ++rit ) {
  std::cout << *rit;

W C++03/11 większość standardowych kontenerów posiada również metodę .rbegin() i .rend().

Na koniec możesz napisać Adapter zakresu backwards w następujący sposób:

namespace adl_aux {
  using std::begin; using std::end;
  template<class C>
  decltype( begin( std::declval<C>() ) ) adl_begin( C&& c ) {
    return begin(std::forward<C>(c));
  }
  template<class C>
  decltype( end( std::declval<C>() ) ) adl_end( C&& c ) {
    return end(std::forward<C>(c));
  }
}

template<class It>
struct simple_range {
  It b_, e_;
  simple_range():b_(),e_(){}
  It begin() const { return b_; }
  It end() const { return e_; }
  simple_range( It b, It e ):b_(b), e_(e) {}

  template<class OtherRange>
  simple_range( OtherRange&& o ):
    simple_range(adl_aux::adl_begin(o), adl_aux::adl_end(o))
  {}

  // explicit defaults:
  simple_range( simple_range const& o ) = default;
  simple_range( simple_range && o ) = default;
  simple_range& operator=( simple_range const& o ) = default;
  simple_range& operator=( simple_range && o ) = default;
};
template<class C>
simple_range< decltype( reversed( adl_aux::adl_begin( std::declval<C&>() ) ) ) >
backwards( C&& c ) {
  return { reversed( adl_aux::adl_end(c) ), reversed( adl_aux::adl_begin(c) ) };
}

A teraz możesz to zrobić:

for (auto&& x : backwards(ctnr))
  std::cout << x;
Która moim zdaniem jest całkiem ładna.
 4
Author: Yakk - Adam Nevraumont,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-27 15:19:30

Użyj iteratorów odwrotnych i pętli od rbegin() do rend()

 2
Author: Steve Townsend,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-18 05:18:31

Użyj tego kodu

//print the vector element in reverse order by normal iterator.
cout <<"print the vector element in reverse order by normal iterator." <<endl;
vector<string>::iterator iter=vec.end();
--iter;
while (iter != vec.begin())
{
    cout << *iter  << " "; 
    --iter;
}
 -1
Author: amit kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-22 12:30:49