MySQL Java JavaScript PHP Python HTML-CSS C-sharp C++ Go

Copierea elementelor

Funcția std::copy_if() se folosește pentru a copia valorile care îndeplinesc un anumit criteriu dintr-un interval într-altul. Această funcție are mai multe versiuni, iar una dintre ele este următoarea:

iterator std::copy_if(start_source_iterator, end_source_iterator, start_dest_iterator, condition)

Primele două argumente – start_source_iterator și end_source_iterator – reprezintă iteratorii de început și sfârșit ai intervalului de valori din care trebuie să copiem valorile. Al treilea argument – start_dest_iterator – reprezintă iteratorul de început al intervalului în care trebuie să inserăm valorile copiate.

Ultimul parametru – condition – reprezintă condiția. Condiția este o funcție care primește o valoare de tip arbitrar și returnează un rezultat de tip bool - true dacă valoarea satisface condiția și false dacă nu o satisface.

Rezultatul funcției este un iterator care indică adresa imediat următoare ultimei valori copiate din intervalul sursă.

Să vedem un exemplu de utilizare a funcției:

#include <iostream>
#include <vector>
#include <algorithm>

// dacă numărul este par
bool is_even(int n) { return n % 2 == 0; }
// dacă numărul este pozitiv
bool is_positive(int n) { return n > 0; }

// pentru a afișa un vector pe consolă
void print(const std::vector<int>& data)
{
    for (const auto& n : data)
    {
        std::cout << n << "\t";
    }
    std::cout << std::endl;
}

int main()
{
    std::vector<int> numbers { -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 };
    std::vector<int> even_numbers(numbers.size());
    std::vector<int> pos_numbers(numbers.size());

    auto end_even_iter = std::copy_if(begin(numbers), end(numbers), begin(even_numbers), is_even);
    even_numbers.erase(end_even_iter, end(even_numbers));
    print(even_numbers);   //   -4      -2      0       2       4

    auto end_pos_iter = std::copy_if(begin(numbers), end(numbers), begin(pos_numbers), is_positive);
    pos_numbers.erase(end_pos_iter, end(pos_numbers));
    print(pos_numbers);   //    1       2       3       4       5
}

În acest exemplu, copiem din vectorul de numere numbers în două alte vectori – even_numbers și pos_numbers. Observați că pentru ambii vectori finali este setată lungimea:

std::vector<int> even_numbers(numbers.size());
std::vector<int> pos_numbers(numbers.size());

Teoretic, toate elementele din vectorul numbers ar putea îndeplini condiția, de aceea lungimea vectorilor even_numbers și pos_numbers este setată la dimensiunea vectorului numbers.

Condițiile sunt definite prin funcțiile separate – is_even (verifică dacă numărul este par) și is_positive (verifică dacă numărul este pozitiv).

Mai întâi, copiem din vectorul numbers în vectorul even_numbers toate numerele care sunt pare:

auto end_even_iter = std::copy_if(begin(numbers), end(numbers), begin(even_numbers), is_even);

Aici, intervalul de căutare este definit de iteratorii pentru începutul și sfârșitul vectorului numbers. Elementele copiate vor fi plasate de la începutul vectorului even_numbers, iar condiția va fi funcția is_even.

De fapt, funcționarea acestei funcții ar putea arăta astfel:

auto output_iter = begin(even_numbers);
for (auto input_iter = begin(numbers); input_iter != end(numbers); ++input_iter)
{
    if (*input_iter % 2 == 0)
    {
        *output_iter++ = *input_iter;   // atribuim valorile prin iteratorul de destinație
    }
}
// returnăm iteratorul
auto end_even_iter = output_iter;

Astfel, toate numerele pare din numbers vor fi copiate în even_numbers. Dar există o problemă – nu toate elementele din vectorul numbers vor fi pare, iar dimensiunea inițială a vectorului even_numbers este aceeași cu a vectorului numbers. Pentru a păstra doar numărul de elemente copiate în even_numbers, tăiem vectorul even_numbers până la poziția ultimului element copiat, la care se referă iteratorul end_even_iter.

even_numbers.erase(end_even_iter, end(even_numbers));

În mod similar, copiem numerele pozitive, dar folosim funcția is_positive ca condiție:

auto end_pos_iter = std::copy_if(begin(numbers), end(numbers), begin(pos_numbers), is_positive);
pos_numbers.erase(end_pos_iter, end(pos_numbers));

Ieșirea pe consolă va fi:

-4      -2      0       2       4
1       2       3       4       5